一次內聯元素錯位引起對line-height的思考

做者:李一睿css

line-height 對於一個前端小可愛來講,應該是一個會常常碰面的老朋友了。但是有一天,我忽然發現本身好像對他沒那麼瞭解,他也沒有外表看起來的那麼簡單。html

事情的通過是這樣的……前端

在偶然一次工做中,我寫了這樣的模板:字體

<div>
    <span class="name">重大疾病險</span>
    <span class="tip">保額每個月可累計</span>
</div>
複製代碼
div{
    font-family: "PingFang SC";
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
複製代碼

兩個相鄰的內聯元素,字體一大一小,行高相同,因爲第二段文字須要有字多狀況就自動去下一行的效果,因此第二個spaninline-block我暢想的結果是,兩個 span 高度都是 20px, div 高度也是 20px,多麼完美。但結果每每不近人意……spa

div 的高度怎麼是 28??3d

再一看子元素,一個 28 一個 20??code

  • 疑問1:難道是 line-height 對行內元素不生效??orm

    然而規範告訴我,對於非替代的 inline 元素,它用於計算行盒(line box)的高度。cdn

  • 疑問2:既然生效了,爲何審查元素看着是 28,不是 20 呢?htm

    對於文原本說,存在一個內容區域(content area)。你能夠理解爲,用光標選中這行文字時帶背景的區域。他同時受 font-family 和 font-size 的影響。就算是相同的字號,若是字體不一樣,‘你所看到’的高度也是不同的,同窗們能夠本身嘗試一下。這裏強調你所看到的,也就是咱們這裏的 28px,它實際上是這個文本內容區的高度,而內容區的高度並非真正的高度,也就是說,它不會影響這個元素真正的尺寸,也不會撐起父元素的高度,因此只是一個你看起來的高度。而對於行內元素來講,真正影響它高度的就是line-height

    在這裏,咱們能夠經過改變他們的 font-family 來證明一下。

    div{
          font-family: "HelveticaNeue";
      }
      .name{
          line-height: 20px;
          font-size: 20px;
      }
      .tip{
          display: inline-block;
          line-height: 20px;
          font-size: 14px;
      }
    複製代碼

    能夠看到,更改了字體以後,.name的高度由28變成了24,.tip因爲是inline-block因此高度沒變,可是父div的高度依然是28px,說明content area並不會影響父元素的真實高度。

  • 疑問3:那如何看到它真正的高度?

    你可能也發現了,第二個 span 是inline-block,它的高度就是 20px,那咱們將第一個span也設置成inline-block來看一下。

    果真,它的高度終於變成了咱們指望的 20px。
    那咱們再來看一下父元素div的高度:

    !!怎麼仍是 28px??

  • 疑問4:兩個子元素都已是 20px 了,爲何父元素仍是 28px?

    這裏先聲明兩個問題:

    1. 證實前面疑問2中說的沒錯,content area 是不會影響實際尺寸的,如今咱們元素都是 20px 了,可父元素依然仍是 28px。
    2. 咱們將第一個 span 設置成inline-block以後,能夠看到它的尺寸已經變成了 20px,但這並不表明這它就沒有 content area 了,或者它的 content area 變成了 20px。你能夠理解爲咱們給他外面包了一層盒子,你能夠看到盒子的真正的尺寸,而 content area 在它裏面,你只是看不到罷了。更況且,它是一個影響不了誰的東西。

    接着回到咱們的問題,仔細看上圖,能夠發現,兩個高度都是 20px 的子元素,上下都有必定的間隙;再仔細看,發現它倆沒對齊,紅色背景的靠上,粉色背景的靠下,它倆之間稍微有些錯位。就是這些,讓咱們的父元素被撐成了 28px。那它們又是從哪裏來的呢?

    既然是對不齊致使父元素被撐高了,那 CSS 中相關對齊的屬性,咱們很容易想到是vertical-align,難道是它搞得鬼?那咱們試着改一下它們的vertical-align

    vertical-align:top,上面對不齊了

    vertical-align:middle,好像跟以前差異不大……

    雖然說這些屬性值都沒能讓他們對齊,但能夠發現確實是與它有關的,多是咱們哪裏使用不當,影響了這個屬性?那咱們就去了解一下vertical-align是怎麼對齊的,起初咱們不設置的時候,會取它的默認值:baseline—— 基線對齊。

    內聯元素默認是基線對齊的,而基線就是指行框盒子中字母'x' 的下邊緣:

    誒??再仔細看看咱們以前對不齊的那張圖,你會發現,雖然元素沒對齊,可是文字下端是對齊的,這不就是正常的基線對齊嗎!這下就說的通了。

    劃重點!!

    行內元素的對齊方式默認是基線對齊,也就是都與 x 的下邊緣對齊。這兩個 span 的高度是同樣的,都是 20px,然而重點就在於它們的字體大小不同。而文本在若是設置了line-height,是會基於line-height居中的,也就是說,它們分別在各自高度相同框框中居中,但因爲字號大小不同,因此文字底部是對不齊的,但他們又須要基線對齊,因此它倆開就必需要錯位一下。

    這裏引用一下鑫旭大神的圖:

  • 疑問5:那這是否是就說明,咱們把兩個元素的行高設置成不同,就能夠不錯位把父元素撐高了?

    這裏咱們分別給兩個span設置與本身字體大小同樣的行高:20px 和 14px,能夠看到它倆已經沒有向外錯位了,可是父元素的高度並無如期,仍是 28px。怎麼回事?難道還有別的東西再影響它?

    你猜對了,但這是個咱們看不見的東西。引用一下張鑫旭大神的叫法——幽靈空白節點。

    「幽靈空白節點」是內聯盒模型中很是重要的一個概念,具體指的是:在 HTML5 文檔聲明 中,內聯元素的全部解析和渲染表現就如同每一個行框盒子的前面有一個「空白節點」同樣。這 個「空白節點」永遠透明,不佔據任何寬度,看不見也沒法經過腳本獲取,就好像幽靈同樣, 但又確確實實地存在,表現如同文本節點同樣,所以,我稱之爲「幽靈空白節點」。

    既然看不見,那咱們能夠拿一個看的見的 x 字符來僞裝它。

    <div>
          <em>x</em>
          <span class="name">重大疾病險</span>
          <span class="tip">保額每個月可累計</span>
      </div>
    複製代碼
    div{
          font-family: "PingFang SC";
      }
      em{
          display:inline-block; /*爲了審查元素看到的不是content area*/
          font-style:normal;
      }
      .name{
          line-height: 20px;
          font-size: 20px;
      }
      .tip{
          display: inline-block;
          line-height: 20px;
          font-size: 14px;
      }
    複製代碼

    這個 'x' 字號和行高都沒有設置,字號是繼承下來的 20px,元素行高默認是 1.x(1.x 倍的 font-size),具體數值還有待研究,但絕對是 >1 的,由圖可見,什麼都沒有設置的狀況下,這個 'x' 的高度就是 28px,也就表明着,那個幽靈空白節點的高度就是 28px。

    那咱們將幽靈空白節點的行高設小一些不就行了?但是這個幽靈節點,看不見摸不着,怎麼設啊。別忘了,line-heigt是可繼承性的,咱們給父div設置line-heigt,幽靈節點天然就會繼承。

如何解決

明白了上述的疑問以及原理,接下來就看下怎麼解決這個問題。

解決一

咱們能夠給父divline-height設置一個很小的值

div{
    line-height: 5px;
    font-family: "PingFang SC";
}
em{
    display:inline-block; /*爲了審查元素看到的不是content area*/
    font-style:normal;
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
複製代碼

這樣,幽靈節點的行高就只有 5px,父元素行高 20px,沒毛病。但這個方法還不夠完美,由於你須要想一下這個很小的值……

解決二

當 line-height 設置爲一個無單位的數值時,表示是某倍的font-size。

div{
    line-height: 1;
    font-family: "PingFang SC";
}
em{
    display:inline-block; /*爲了審查元素看到的不是content area*/
    font-style:normal;
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
複製代碼

給父元素設置line-height爲1,這樣,子元素高度都是本身的font-size,包括幽靈空白節點。這樣就不會再有人無心間撐高父元素了。固然,除非你的幽靈空白節點繼承下來了一個很大的 font-size, 這點你得明白。

解決三

既然行高能夠與 font-size 有關,font-size 也是可繼承的,那咱們將父元素的 font-size 設爲 0

div{
    font-size: 0px;
    font-family: "PingFang SC";
}
em{
    display:inline-block; /*爲了審查元素看到的不是content area*/
    font-style:normal;
}
.name{
    line-height: 20px;
    font-size: 20px;
}
.tip{
    display: inline-block;
    line-height: 20px;
    font-size: 14px;
}
複製代碼

能夠看到,咱們模仿的那個幽靈節點已經沒有了,寬高都是 0 了,父元素的高度也天然就回到了 20px。

總結

以上,能夠說是我對行內元素對齊問題的一些思考總結吧。若是你還有疑問,能夠再多看幾遍,本身嘗試一下再繼續思考思考。這個問題我也是來來回回想了好多遍,也歡迎你們評論提問,咱們能夠一塊兒討論~

前端小白,有講解錯誤或不全之處,還望大佬們嘴下留情,歡迎指正~

相關文章
相關標籤/搜索