Vertical-Align: 你應該知道的事情

平時遇到vertical-align時候會有各類抓狂的時刻,調來調去雖然也弄好了可是內心面一直很虛,由於一直沒有透徹理解過這個屬性,搜索時候發現了一篇很棒的文章,算是半翻譯吧,把這個屬性好好總結一下。css

引言

提及vertical-align你們都知道他是用在對相鄰的文字和內聯元素上,好比常見的將一個圖標和相鄰的文字居中對齊。可是當你不瞭解他的機制時候常常會讓你抓狂,所以咱們一次來攻克這個規則的玄機。前端

vertical-align是如何做用於行框中的內聯元素

vertical-align用來對齊內聯級元素,也就是display值爲inlineinline-block或者inline-table(這個一般不考慮了)的元素。
inline元素也就是包含文字的最基本的標籤如span
inline-block,顧名思義就是表現爲行內的塊級元素,能夠設置寬度、高度和間距邊框等。佈局

內聯級元素以行的形式相鄰排列在一塊兒,一旦有更多的內聯級元素超過當前行能容納的長度,就會在其下面產生一個新行。也就是咱們常說的line box(行框),行框包含其行內全部內容。不一樣尺寸的內容意味着行框也有不一樣的高度。下圖就用紅線標註了三個行框的top和bottom。
圖片描述字體

行框勾勒出了這些內容佔據的區域,其中vertical-align就負責對行框中的各個元素進行對齊。問題來了,這些元素都是相對於哪些線對齊呢?spa

關於baselines, tops, bottoms你要知道的

垂直對齊最關鍵的參考線就是元素的基線baselines,在某些狀況下元素的包含盒的頂端線tops和底端線bottoms也變得很重要。下面就分別看看各類類型元素的baselines、tops和bottoms。.net

inline元素

圖片描述

如圖所示,有三行不一樣標線的文字。紅線表明line-height的頂端和底端;綠線表明文字字體的高度,這裏須要注意的是其實文字內容區域實際佔據的高度並不嚴格等於字體高度而是由font-sizefont-family共同決定的,特殊狀況就是宋體字體下,實際內容區域高度就等於字體高度。可是這點差距通常狀況下也無傷大雅,咱們就假定用字體高度來表示內容區域高度便可;藍線表明基線baseline,能夠理解爲字母x的底邊緣線,就是比字體高度中心位置低大約1/2的x高度。翻譯

左圖的行高設置爲同字體高度相同,所以紅線和綠線重合了。中圖行高設置爲兩倍字體高度,行間距分爲上下兩部分等分了一個字體高度,即相對於綠線分別向上向下半個字體高度。右圖行高設置爲字體高度的一半,即相對於綠線分別向下向上四分之一字體高度。3d

inline-block元素

圖片描述

從左到右分別是包含流內in-flow內容的inline-block元素、包含流內in-flow內容的inline-block元素同時設置了overflow:hidden和一個不含流內內容可是有高度的inline-block元素。紅線表面了inline-block元素的外邊距margin邊界,圖中盒模型黃色是border,淺綠是padding,淺藍是content;藍線表示inline-block元素的baseline。code

能夠得出,inline-block元素外部邊緣線就是margin-box的頂端和底端邊界,也就是圖中的紅線。基線的規則判斷比較複雜,能夠簡單記爲:若不包含內容或者overflow屬性不爲visible之外的值,則其基線就是底部邊緣線,也就是margin-box的底端邊界。blog

行框line box

圖片描述

上圖用幾根線很清晰的表現出了行框的結構。綠線表明的是行框中text box,這裏稱做字框的的頂端和底端線。同時用灰色背景高亮了文字的區域。

行框頂線和其中最高的元素對齊,行框底線和其中最低元素對齊。

行框的基線在草案中並未做出精確的定義:

CSS 2.1 does not define the position of the line box's baseline. — the W3C Specs

這多是最讓人困惑的地方了,他的意思就是行框的基線就位於能同時知足全部其餘vertical-align和最小化行框高度的位置。這樣說仍是很抽象,可是有個可讓其具象的方法,也就是像圖中那樣在行框的最前面加上一個x字符,這個字符就是對齊了基線baseline

圍繞着這個基線的綠線也就是字框,能夠理解爲行框中一個沒有任何對齊方式的內聯元素,其高度等於字體的高度(如前面說的同樣,不考慮字體的因素了)。草案中把咱們這裏用字符x模擬的看不見字框稱做strut,張鑫旭大神在其博客中稱爲幽靈空白節點。
總結下,行框就是vertial-align發揮做用的區域,他包括一個基線、字框、頂線和底線。每一個內聯元素也有其本身的基線,頂線和底線。

vertical-align對齊baselines,tops,bottoms

圖片描述

用上圖表示各類對齊方式的形式。

  • baseline: 內聯元素的基線正好位於行框基線上。
  • sub:內聯元素的基線位置低於行框的基線。
  • super:內聯元素的基線位置高於行框的基線。
  • <percentage>:內聯元素的基線相對於行框基線移動相應於行高百分比的數值。
  • <length>:內聯元素的基線相對於行框基線移動某個絕對數值。
  • middle:居中對齊能夠着重講一下,他的意思就是內聯元素的頂線和底線的中線與行框的基線向上偏移二分之一個x-height,能夠近似理解爲字符x中間交叉點。

圖片描述

  • text-top: 內聯元素頂線與行框的字框頂線對齊。
  • text-bottom: 內聯元素底線與行框的字框底線對齊。

圖片描述

  • top: 內聯元素頂線與行框頂線對齊。
  • bottom: 內聯元素底線與行框底線對齊。

圖片描述

案例分析:vertical-align爲什麼如此表現

圖片和文字對齊是前端開發者最多見的場景了,雖然如今不少都用字體圖標或者用一些組件不少狀況下不須要考慮對齊了,可是當你本身寫的時候仍是務必要搞清楚這個基本原理。下面看這個例子。

居中圖標

一個圖標相鄰有一行文字,若是讓文字和圖標居中對齊,大部分人會對圖標使用vertical-align: middle,可是你會發現好像並未真正的居中對齊:

圖片描述

上圖兩邊的對比很明顯,左邊文字有些許偏上,右邊纔是完美的居中對齊,兩邊的代碼以下:

<!-- left mark-up -->
<span class="icon middle"></span>
Centered?

<!-- right mark-up -->
<span class="icon middle"></span>
<span class="middle">Centered!</span>

<style type="text/css">
  .icon   { display: inline-block;
            /* size, color, etc. */ }

  .middle { vertical-align: middle; }
</style>

這是爲什麼呢?

畫出輔助線來看一下:

圖片描述

很明顯了,左圖的文字是默認基線對齊的,以x的中線位置分割帶有ascender的文字會偏上一些。

而右圖對文字用span標籤包裹而後對整個文字內容區域也使用middle,這樣其基線位置相對於行框基線會稍微下沉一些,這樣就與圖標居中對齊了。

行框基線位置的移動變化

前面提過,行框基線的位置會被行內全部元素所影響,而大多對齊方式都是和行框基線有關的,所以假如行框基線發生了變化,整個佈局就會出現變化。

舉例說明:

  • 假若有一個很高的內聯元素高度高於了以前行框高度時候,看看此時行框佔據的空間如何變化,下圖左邊高的內聯元素text-botttom對齊,右邊text-top對齊。能夠看到行框基線和頂線,底線的位置。

圖片描述

<!-- left mark-up -->
<span class="tall-box text-bottom"></span>
<span class="short-box"></span>

<!-- right mark-up -->
<span class="tall-box text-top"></span>
<span class="short-box"></span>

<style type="text/css">
  .tall-box,
  .short-box   { display: inline-block;
                /* size, color, etc. */ }

  .text-bottom { vertical-align: text-bottom; }
  .text-top    { vertical-align: text-top; }
</style>

內聯元素下面的間隙

咱們再來思考下常常遇到的一個場景:

圖片描述

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

<style type="text/css">
  .box { display: inline-block;
         /* size, color, etc. */ }
</style>

內聯元素下面總會有一個間隙,就是由於幽靈空白節點在做怪,內聯塊的基線如今就是底邊緣線和字框的基線對齊後,間隙就是字框基線下的descender,爲避免這種問題其實就是改變行框基線的位置便可,好比topmiddle均可。

圖片描述

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

<style type="text/css">
  .box    { display: inline-block;
            /* size, color, etc. */ }

  .middle { vertical-align: middle; }
</style>

總結

之後再遇見對齊的問題,只須要搞清楚兩個問題就能夠了:

  • 行框的基線、頂線、底線在哪裏?
  • 內聯元素的基線、頂線、底線在哪裏?
相關文章
相關標籤/搜索