line box,inline box及vertical-align分析

1、適用元素

vertical-align適用於inline-level元素,即inline,inline-block或inline-table 。css

2、inline與inline-block元素的外邊緣和基線

inline元素的外邊緣和基線

inline元素的外邊緣是由它的line-height決定的。

clipboard.png

  • 紅線:元素外邊緣,即行高的頂部和底部邊緣html

  • 綠線:字體的高度。web

  • 藍線:基線。segmentfault

上圖中,左側的那個,文本的行高設置爲與字體大小相同的高度。上下兩邊綠色和紅色的線均重合爲一條線。中間的那個,行高是字體高的兩倍。右邊的那個,行高是字體高的一半。字體

inline-block元素的外邊緣和基線

inline-block元素的外邊緣就是它的margin-box的頂部和底部邊緣。

clipboard.png

  • 紅線:元素外邊緣,即margin-box的頂部和底部邊緣spa

  • 藍線:基線。3d

上圖中從左到右能夠看到:一個inline-block元素裏面有in-flow內容(一個「C」),一個inline-block元素有in-flow內容和overflow: hidden,一個inline-block元素沒有in-flow內容(可是內容區域有高度)。code

Inline-block元素的基線取決於元素是否具備in-flow內容orm

  • 有in-flow內容,inline-block元素的基線是普通流中最後一個內容元素的基線(例如左邊那個)。對於最後一個元素,它的基線是根據它本身的規則肯定位置的。htm

  • 有in-flow內容而且使用了值不是visible的overflow,基線就在margin-box的底部邊緣那個位置(例如中間那個)。所以,它與inline-block元素的底部邊緣同樣。

  • 沒有in-flow內容,基線也是在margin-box的底部邊緣那個位置(例如右邊那個)。

例如:下圖中紫色爲基線,兩個span均是基線對齊。兩幅圖對比能夠看出,隨着第一個span元素中內容的增多,基線下移了。

<style type="text/css">
  .box {
    display: inline-block;
    width: 100px;
    height: 50px;
    border: 1px solid red;
  }
  </style>
 <div>
    <span class="box">士大夫和健康</span>
    <span class="box"></span>
  </div>

clipboard.png

<style type="text/css">
  .box {
    display: inline-block;
    width: 100px;
    height: 50px;
    border: 1px solid red;
  }
  </style>
 <div>
    <span class="box">士大夫和健康士大夫和健康</span>
    <span class="box"></span>
  </div>

clipboard.png

【注】:若是一個元素是浮動的(float:left/right),絕對定位的(position:absolute/fixed)或者是根元素(html),那麼它被稱之爲流外的元素(out-of-flow)。若是一個元素不是流外的元素,那麼它被稱之爲流內的元素(in-flow)。

3、content-area、inline box和line box

content-area:在非替換元素中,指元素中每一個字符的字體大小串在一塊兒所組成的框;在替換元素中,元素的固有高度加上任何margins, borders或padding。

inline box:每一個元素的content-area加上leading。對於非替換元素,元素的inline box的高度等於line-height的值;對於替換元素,元素的inline box的高度等於該元素的固有高度加上任何margins, borders或 padding。

line box:一行就是一個line box。line box的邊界是該行內inline boxes的最高點和最低點,即line box的頂部邊緣是該行內最高inline box的頂部邊緣,底部邊緣是該行內最底inline box的底部邊緣。

line box的文本盒和基線

文本盒能夠當作是放在line box裏面的沒有任何對齊的行內元素。文本盒的高度等於它的父元素的字體大小。所以,文本盒只是把line box的無格式文本圍起來了。這個盒子就是下圖中用綠線標出來的那個。由於這個文本盒與基線相關聯,當基線移動時,它也移動。

line box的基線沒法定義。line box的基線被放在可以實現全部條件的地方。

clipboard.png
綠色:line box的文本盒。
紅色:line box的頂部和底部邊緣。
藍色:基線。
灰色:文本元素的區域。

查看line box基線的方法:在行的開頭增長一個字符,就像上圖中增長的「X」。它默認地坐在基線上。line box是垂直對齊發生的區域。line box有一條基線,一個文本盒和一個頂部和底部邊緣。

line box高如何計算

  1. 當一行中僅有行內不可替換元素,且這些元素都是相同的 font-size、line-height和vertical-align。則content-area=font-size, line-box的高=line-height。

  2. 當一行中包含行內元素,這些元素包括可替換和不可替換,這些元素有不一樣的 font-size和 line-height。則按如下方式計算:content-area的高由每一個不可替換元素的font-size,以及替換元素的固有高度和任何padding, borders,或margins決定。leading應用於每個元素,一半放在頂部,一半放在底部。line box的頂部邊緣是該行內最高inline box的頂部邊緣,底部邊緣是該行內最底inline box的底部邊緣。

例如:

<P style="line-height: 12pt; font-size: 12pt;">
      <A style="font-size: 128pt;">anchor</A> angry text
      <B style="vertical-align: top">bold</B>
</P>

anchor的content-area是128pt,可是他的inline box是12pt。假設字體是Helvetica,那麼

descent : 128pt*219/1000=28pt
ascent :  128pt*781/1000=100pt
halfleading : (12pt-128pt)/2 = -58pt
inline box的top:100pt-58pt=42pt
inline box的bottom:58pt-28pt=30pt

因此這個inline box的top爲基線上42pt,bottom爲基線上30pt。同理可得匿名文本angry text的top是基線上10pt,基線下2pt。因此line-box的高是44pt:基線上42pt,基線下2pt。

clipboard.png

將angry text文本去掉,會發現父元素P高度不變。
緣由:根據W3C規範
在由inline-level元素組成的塊容器元素中,line-height肯定了該元素內部line boxes的最小高度。這個最小高度由基線上的最小高度和基線下的最小深度組成,就像每一個line box都是由寬度爲零,擁有父元素的font-size和line-height的inline box(假想元素)開始的。
個人理解是line box是在這個假想元素的基礎上往兩邊延伸。例如:

<P style="line-height: 44pt; font-size: 12pt;">
      <A style="font-size: 128pt;">anchor</A>
    </P>

clipboard.png
p元素中只有anchor文本,可是該文本的inline box的top爲基線上42pt,bottom爲基線上30pt。因此line box的top爲基線上42pt,而line box的bottom不是基線上的30pt,而是原先假想元素的基線下的最小深度(即上圖中藍線到最後一條紅線的距離)。

所以,即便沒有angry text文本,基線下也會有一個最小深度,因此致使P元素的高度不變。

注:

  1. 例子中計算Helvetica字體用的219和781是修改過的數據,只是爲了讓數據好看點,實際應該是接近於225和775。

  2. leading = line-height - font-size。
    其中一半leading加到文字上方,另外一半leading加到文字下方。

  3. clipboard.png

  4. line-height對可替換元素的inline box沒有影響,可是當該元素的vertical-align值爲百分比時,是有影響的。

4、Vertical-Align的值

clipboard.png

  • baseline:元素的基線在line box的基線頂部。

  • sub:元素的基線移動到line box基線如下。

  • <percentage>:元素的基線經過與line-height相關聯的percentage ,相對於line box的基線進行偏移。

  • <length>:元素的基線經過絕對長度相對於line box的基線進行偏移。

clipboard.png

  • middle:元素頂部和底部二者間的中點與line box的基線加上二分之一的x-height對齊。

clipboard.png

  • text-top:元素的頂部邊緣與line box的文本盒的頂部邊緣對齊。

  • text-bottom:元素的底部邊緣與line box的文本盒的底部邊緣對齊。

clipboard.png

  • top: 元素的頂部邊緣與line box的頂部邊緣對齊。

  • bottom:元素的底部邊緣與line box的底部邊緣對齊。

5、Vertical-Align的詭異行徑

Line Box的基線的移動

例如:

div {
    font-size: 16px;
    line-height: 1;
    background-color: #eee;
    margin-top: 10px;
  }
  
  .tall-box {
    border: 1px solid red;
    width: 40px;
    height: 40px;
    display: inline-block;
  }
  
  .short-box {
    border: 1px solid black;
    width: 40px;
    height: 10px;
    display: inline-block;
  }
  <div>
    <span class="tall-box" style="vertical-align: text-top;">    </span>
    <span>Exg</span>
    <span class="short-box"></span>
  </div>

clipboard.png

若將tall-box的vertical-align變成top,得下圖

clipboard.png

從上下兩幅圖對比能夠看出,隨着vertical-align從text-top變成top,Exg往上移,致使字體高超出了父div的邊界。這是因爲line-height的高小於字體高。

若將第一個圖中的父div的line-height變爲2,使Exg的line-height值大於字體本來的高度,則得下圖。從圖中能夠看到,紅框降低了,父div的高度變高了。這是因爲紅框是text-top對齊,由此可知道基線位置在哪裏。而基線位置的肯定能夠肯定Exg和黑框的位置。而line box的頂部邊緣是該行內最高元素的頂部邊緣,這時候最高的是Exg,所以能夠看到紅框降低,父元素變高了。

clipboard.png

Inline-Level元素的底下間隙

<ul>
  <li class="box"></li>
  <li class="box"></li>
  <li class="box"></li>
</ul>

<style type="text/css">
  .box{
    display: inline-block;
   }
</style>

clipboard.png

能夠看到li元素底下有間隙。

間隙產生的緣由:由於列表項位於基線上,而在基線下是放文本descenders空間。

取消該間隙的方法:

  1. 設置li元素vertical-align: middle;

  2. 在li元素內添加內容。由於內容會將基線上移。

參考自:
inline-format
【譯】Vertical-Align: All You Need To Know

相關文章
相關標籤/搜索