關於 vertical-align 的一些小知識

引子

在平常開發過程當中,咱們常常會遇到以下的場景,一行中既有圖片也有文字,並且圖片還要和文字對齊。效果以下:
css

一般代碼以下:html

<!DOCTYPE html>
<html>
<head>
    <title>Test</title>
    <style type="text/css">
        .text {
            background-color: grey;
        }
    </style>
</head>
<body>
<img src="warn.png"><span class="text">some text.</span>
</body>
</html>

獲得的效果倒是這樣的:字體

修改下文本爲行內塊盒子,並設置行高與盒子高度(盒子高度與圖片高度相同)一致,效果以下:spa

咱們發現文本區域始終與圖片錯開了一些。怎麼解決呢?設置文字的 margin 或者將圖片浮動並非咱們想要的方案。
那麼究竟是什麼緣由致使了上面的問題呢?各類搜索後,發現其實是行盒子內部在豎直方向上的對齊方式在做祟。
在搜索過程當中發現一篇很不錯的介紹 vertical-align 的文章,搬運以下,原文請參考Vertical-Align: All You Need To Know.net

基本概念

vertical-align 被用來對齊行級元素(inline-level elements)。所謂的行級元素就是那些 display 屬性爲以下值得元素:3d

  • inline;
  • inline-block;
  • inline-table(不在本文範圍內);

Inline elements 基本上都是一些包含文本的標籤(span etc.)。
Inline-block elements,顧名思義,就是行內的塊元素,它們能夠擁有高度、寬度、內邊距、邊框和外邊距。code

咱們都知道,行級元素沿着當前行依次排列,噹噹前行已經被填滿時會從新建立一行。這些行就是所謂的行盒子(line box)。每一個行盒子的高度依它們各自的內容的高度的不一樣而不一樣。下圖就展現不一樣高度的行盒子,紅線表示行盒子的上下邊界。
htm

在這些行盒子內部,元素經過 vertical-align 屬性來進行對齊,那具體是參照什麼來對齊呢?blog

baseline 和 外邊界(outer edges)

對於豎直方向上的對齊來講,最重要的一個參考點就是元素的 baseline。在某些狀況下也會參考元素盒子(element's enclosing box)的上下邊界。圖片

上圖中,紅線表示行高的上下邊界;綠線表示文字的高度;藍線表示 baseline 的位置。在左圖中,文本的高度與行高相同,紅線和綠線重合了。在中間的圖中,行高是文本高度的兩倍。在右圖中,行高是文本高度的一半。

行內元素的外邊界與行高的上下邊界對齊。若是行高低於文本的高度也沒關係,元素的外邊界如上圖中的紅線。
行內元素的 baseline 就是文字所在的線。粗略的說,baseline 的位置就在文本高度的中間往下的某個位置,具體能夠參照 W3C 的詳細定義

從左到右依次爲:擁有流內(in-flow)內容(一個「c」)的行內塊元素,一個擁有流內內容可是設置了 overflow:hidden 的行內塊元素,以及一個擁有脫離了文檔流的內容的行內塊元素。元素的 margin 邊界由紅線表示,border 爲黃色,padding 爲綠色,內容爲藍色。每一個行內塊元素的 baseline 由藍色線表示。

行內塊元素的外邊界就是它的margin盒子(margin-box)的上下邊界。也就是上圖中的紅線標示的區域。
行內塊元素的 baseline的位置取決於它是否有流內內容(in-flow content):

  • 當行內塊元素的內容都在文檔流中時,元素的 baseline 的位置由元素內容中最後一個元素的 baseline 的位置決定(參考左圖)。最後一個元素的 baseline 的位置根據該元素本身的規則肯定。
  • 當行內元素的內容都在文檔流中,但 overflow 屬性的計算值不爲 visible 時,baseline 的位置由 margin 盒子(margin-box)的下邊界(bottom-edge)決定(參考中間圖)。所以,baseline 的位置與行內塊元素的底邊界的位置相同。
  • 當行內塊元素的內容徹底脫離文檔流時,baseline 的位置是 margin 盒子(margin-box)的底邊界(參考右圖)。

上圖中,行盒子(line-box)的上邊界與該行中最上部的元素的上邊界對齊,下邊界與該行中最下部的元素的下邊界對齊。

行盒子的 baseline 是可變的,CSS2.1 並未定義行盒子的 baseline。實際上,baseline 的具體位置在計算方程式中是一個自由參數,它的取值依照同時知足 vertical-align 和最小化行高條件而定。
由於行盒子的 baseline 不可見,咱們能夠經過在行的開頭增長一個字符來肯定 baseline 的位置,正如上圖中的 x 同樣。若是這個字符沒有被指定任何的對齊方式,那麼它默認的對齊方式就是 baseline。
在 baseline 的周圍,行盒子有個叫作文本盒(text box)的區域。文本盒能夠被簡單的看做爲沒有任何對齊方式的行內元素。文本盒的高度與其父元素的字體大小一致。所以,文本盒僅僅包含行盒子中未被格式化的文本。在上圖中,綠線標識出來的區域就是文本盒的位置。由於文本盒與 baseline 相關聯,所以當 baseline 移動的時候文本盒也會跟着移動。

在 W3C 的文檔中,文本盒也被叫作 strut

至此,咱們已經瞭解了全部的基礎知識,總結一下:

  • 每一行中都存在一個行盒子,vertical-align 也僅做用於行盒子。行盒子中包含 baseline,文本盒以及上下邊界。
  • 每一行中都有行級元素,每一個行級元素均可以根據某種方式進行對齊,它們都有一個 baseline,上下邊界。

vertical-align 的取值

  • baseline: 元素的 baseline 與行盒子的 baseline 對齊。
  • sub: 元素的 baseline 被移動到行盒子的 baseline 的下方。
  • super: 元素的 baseline 被移動到行盒子的 baseline 的上方。
  • < percentage>: 元素的 baseline 位置被相對於行盒子的 baseline 移動一段距離,該距離由行高的百分比肯定。
  • < length>:元素的 baseline 位置被相對於行盒子的 baseline 移動一段指定的絕對距離。

  • middle: 元素的上下邊界之間的中點將與行盒子的 baseline 的位置加上一半 x 的高度後所在的位置對齊。

  • text-top: 元素的上邊界與行盒子的文本盒的上邊界對齊。
  • text-bottom: 元素的下邊界與行盒子的文本盒的下邊界對齊。

  • top: 元素的上邊界與行盒子的上邊界對齊。
  • bottom: 元素的下邊界與行盒子的下邊界對齊。

更多詳細定義請參考 W3C。

小結

回到前面提到的問題,之因此圖片與文本始終錯開了一些,是由於在行盒子中,圖片和文本默認都是與行盒子的 baseline 對齊,也就是說圖片的下邊界將與 baseline 對齊,固然也就錯開了一些。這個問題的修改方式就是給圖片加上 vertical-align:middle.

相關文章
相關標籤/搜索