[譯]關於vertical-align:你須要知道的一切

原文:Vertical-Align: All You Need To Knowcss

一般我都有須要垂直對齊在一排上一個接着一個的元素。
CSS提供了不少種可能性。有時,我聽過float來解決問題,有時使用position:absolute,有時甚至會經過添加margin或者padding屬性這種使代碼變得比較髒的方式來達到目的。html

我一點也不喜歡上面這些解決方案。浮動僅僅是頂部對齊而且須要手動清除浮動。絕對定位讓元素脫離文檔流,因此他們再也不影響他們的周邊元素。而使用固定值的外邊距和內邊距會出現細微的差異。安全

可是這裏還有另一種玩法:vertical-align。我認爲他值得更多的讚譽。OK,技術上來講使用vertical-align佈局是一種hack的手段,由於他並非由於實現咱們上面那種需求發明的。儘管如此,你也能夠在不一樣的上下文中使用vertical-align來靈活細緻的擺放元素。不須要知道元素的大小。元素在文檔流中,也能感知其餘元素尺寸的改變。這些都讓vertical-align變成了更有價值的選項。佈局

獨特的vertical-align

可是,vertical-align有時也是個卑鄙小人。使用它工做也會令人有點沮喪。在使用它工做時,這裏會有一些使人難以理解的規則。例如,它可能會發生這樣的狀況,一個元素改變了他本身的vertical-align的值,而他的位置卻一點都沒有改變,改變的倒是同行的其餘元素。我仍然會一次一次被拉入這種奇怪的現象,使我苦惱。字體

不幸的是,大多數資料都講述的比較淺顯。特別是,當咱們想使用vertical-align佈局時。他們對最基本的屬性進行了介紹而且在簡單的例子中解釋元素是如何在一行中進行擺放的。可是,他們並無去解釋它使人感到奇怪的部分。spa

因此,個人目標是使本身完全弄清楚vertical-align究竟是怎麼回事。最後消解我疑問的是W3C's的CSS specifications和標準中演示的一些例子。答案就在文章中。.net

因此,讓咱們來解決掉這場關於規則的遊戲吧。code

使用vertical-align的要求

vertical-align被用於inline-level elements。這些元素的display屬性以下orm

  • inlinehtm

  • inline-block

  • inline-table(這篇文章中,並不考慮這種狀況)

基本的inline元素都是標籤裹着文字。

inline-block元素:是在行內中的塊級元素。他們能夠有寬度和高度(一般狀況下,這取決於他們的內容)。一樣也有padding,margin,border。

行內級元素在一行中一個挨着一個。一旦,這些元素超出了他們的所在行,一個新行便會創建在它下方。這裏的每一行就叫作line box。每一行不一樣尺寸的元素意味着line box不一樣的高度。在下面的例子中紅線表明line box的頂部和底部。

line box尋找咱們放置元素的軌跡。在這些line boxes裏面vertical-align屬性負責擺放單獨的元素。因此什麼樣的元素被用來對齊了呢?

關於基線和邊界線

在一行中垂直襬放元素,最關鍵的參考點是參與的元素的基線。在一些例子中,被關閉盒子的頂部和底部也變得很是重要。讓咱們一塊兒看看基線和外邊緣是如何參與到不一樣類型的元素中的。

Inline Element

clipboard.png

這裏有三行挨着的文字。頂部和底部的邊緣線是行高的邊緣線,它們都是紅線。字體的高度被綠線包裹着。藍色的線表明基線。在最左邊,文字的行高和字體自己的高度同樣高。綠線和紅線發生了重疊。在中間,行高是字體大小的2倍高。在最右邊,行高是字體大小的一半高。

inline element的外邊緣的位置,取決於他們的行高的頂部與底部邊緣。若是行高的高度比字體的高度小。那麼,紅色的外邊緣的位置就如上面提到的同樣。

inline element的基線,在字符放置的位置。在圖中,用藍線表示。初略的講,基線的位置通常是在字體高度一半如下的位置。能夠看看W3C的標準對它的定義,detailed definition

Inline-Block Element

clipboard.png

從左邊到右邊的圖你能夠看到:最左,一個在in-flow內的行內塊級元素。中間,一個在文檔流中的inline-block元素而且帶有overflow: hidden屬性的元素。最右,不在文檔流中的inline-block元素(可是內容區域有高度)。margin的邊界線指向紅線,border是黃色的部分,padding是綠色的部分,內容區域是藍色的部分。每個inline-block元素的基線都用藍線表示。

inline-block元素的外邊緣 是它的margin-box的頂部和底部。在圖上,用紅線來表示。

inline-block元素的基線 依賴於元素是不是文檔流中的元素。

  • 假設內容在文檔流中,inline-block元素的基線是普通流中的最後一個內容元素的基線(最左的例子)。對於最後一個元素的基線根據它本身的規則來找尋。

  • 假設內容在文檔流中,可是元素有overflow屬性除了屬性值爲visible這種狀況,基線在margin-box的底部(最中間的例子)。因此,這等同於在inline-block元素的底部邊緣。

  • 假設內容不在文檔流中,一樣的,margin-box的底部邊緣也是基線的位置所在。(例子在最右邊)

Line Box

clipboard.png

你已經看到了上面元素的放置。此次,我畫了line box的text box頂部和底部的線(如圖中的綠線,更多內容看下文),基線如圖中藍色的線。我在文字元素上加了灰色的背景進行強調。

line box的頂部邊緣與最頂部元素的頂線對齊,底部邊緣與最底部元素的底線對齊。圖中紅線表明的就是line box。

line box的基線是多種多樣的

「CSS2.1 並無對line box基線的位置有明確的定義。-W3C Specs

當使用vertical-align工做時,這多是最使人迷惑的部分。這意味着,基線的位置改變是爲了知足像垂直對齊和下降line box的高度這樣的需求的。也就是說,在方程中,這是一個自由的參數。

由於line box的基線是不可見的,所以它的位置並不會那麼明顯。可是,你能夠容易的使它變得可見。只須要在一行的開頭加上一個字母,就像我在圖中添加的字母"x"。若是這個字母並沒排在一條直線上,那麼x坐落的位置就是基線的位置。

在line box基線的周圍有text box。text box能夠簡單的被認爲是在line box中的行內元素。它的高度等同於它的父元素的文字大小。所以,text box僅僅只是圍繞着line box的非格式化文字。這個盒子在上圖中是指向綠線的位置。text box與基線的位置相關聯,它隨着基線而移動。

哦,如今是最難的部分。如今,咱們把知道的全部事,都表如今了上圖中。讓咱們快速的總結最重要的部分:

  • 這裏有一個區域被叫作line box。這是元素垂直對齊的區域。它有一個基線和一個text box以及頂部與底部邊緣。

  • 這裏有inline-level元素。他們是被對齊的對象。他們有基線以及頂部與底部邊緣。

Vertical-Align的值

經過使用vertical-align的參考點,也就是上文提到的基線和邊界線,將元素放置在合適的位置。

相對於line box的基線放置元素的基線

clipboard.png

  • baseline: 元素的基線恰好放置在line box基線的上。

  • sub: 元素的基線放置在line box基線的下面。

  • super: 元素的基線放置在line box的基線的上面。

  • <percentage> 元素的基線移動相對於line box的基線經過相對於line-height的百分比的值來移動。

  • <length>: 元素的基線相對於line box的基線經過絕對值的大小進行移動。

相對於line box的基線放置元素的外邊緣

clipboard.png

  • middle: 元素的頂部與底部邊緣的中點相對於line box的基線移動x-height的一半的位置對齊。

相對於line box的text box放置元素的外邊緣

clipboard.png

  • text-top: 元素的頂部邊緣被放置在line box的text box的頂部邊緣

  • text-bottom: 元素的底部邊緣被放置在line box的text box的底部邊緣

相對於line box的外邊緣放置元素的外邊緣

clipboard.png

  • top: 元素的頂部邊緣被放置在line box的頂部邊緣

  • bottom: 元素的底部邊緣被放置在line box的底部邊緣

在W3C標準中的定義

Vertical-Align的行爲就如它的表現同樣

如今,咱們能夠在具體的例子中看垂直對齊。特別是,處理一些比較容易出現差錯的狀況。

放置icon在中間

這是一個一直以來都令我煩惱的事情:我有一個icon我想將它放置在一行文字的中間。只只僅僅將icon設置vertical-align: middle,看起來彷佛不是一個安全的方法。看下面的例子。

clipboard.png

<!-- 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>

這裏也是上面這個例子,不過,此次我加了一些你從上文了解到的輔助線,

clipboard.png

這有助於幫咱們理解。由於在左邊的文字並無對齊元素,而是被放置在基線所處的位置。經過使用vertical-align:middle來對齊盒子,咱們將只是將盒子放置在了小寫字母的中間。因此,出頭部分的字母出如今頂部。

在右邊,咱們將所有文字區域放置在垂直方向的中點。經過移動text的基線到line box的基線的下方來實現。結果是文字完美的居中於緊挨着的icon。

移動line box的基線

當咱們使用vertical-align工做時,容易遇到的一個共同的問題:line box的基線會被在同一行中全部元素影響。讓咱們猜一猜,一個元素有可能在這樣被對齊的,經過移動line box的基線。由於大多數垂直對齊(除了頂部和底部)都是相對於基線,這也會致使在同一行的的全部元素的位置都會被調整。

一些例子:

  • 若是在一行中,有一個高的元素佔據了整行的高度,vertical-align對它不會有任何影響。在它的頂部上面與底部下面沒有任何多餘的空間能夠移動它。爲了實現它相對於line box基線的對齊,line box的基線必須移動。矮一點的盒子設置了vertical-align: baseline。在左邊,高盒子根據text-bottom對齊。在右邊,根據text-top對齊。你能夠看到矮盒子的隨着基線位置的改變而改變。

clipboard.png

<!-- 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>

經過其餘vertical-align的值對齊高的元素,也會出現和上面的例子相同的行爲。

  • 一樣的給它設置vertical-align的值分別設爲leftbottom移動基線。而這很奇怪,由於基線本不該該參與。

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

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

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

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

clipboard.png

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

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

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

  .bottom    { vertical-align: bottom; }
  .top       { vertical-align: top; }
</style>
  • 在一行中,放置兩個大致積元素而且移動基線垂直對齊他們以此知足同時對齊。line box的高度被調整(左邊的例子)。添加第三個元素,它並有跑到line box的邊緣由於它的對齊屬性,既沒有影響line box的高度,也沒有影響line box基線的位置(中間的例子)。若是它真的跑到了line box的邊緣,咱們的前兩個盒子會被往下推(最右的例子)。

clipboard.png

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

<!-- mark-up in the middle -->
<span class="tall-box text-bottom"></span>
<span class="tall-box text-top"></span>
<span class="tall-box middle"></span>

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

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

  .middle      { vertical-align: middle; }
  .text-top    { vertical-align: text-top; }
  .text-bottom { vertical-align: text-bottom; }
  .text-100up  { vertical-align: 100%; }
</style>

解開Vertical-Align的神祕面紗

當你知道了規則,這就沒那麼複雜了。若是vertical-align並無按照你想的那樣行動,問本身兩個問題:

  • line box的頂部與底部邊緣和基線在哪裏?

  • inline-level元素的頂部與底部邊緣和基線在哪裏?

這將解決你的問題。

相關文章
相關標籤/搜索