從一個垂直居中的方法深度瞭解基線與 vertical-align

案例:採用僞元素實現垂直居中

今天在一篇文章中無心看到一個利用僞元素實現垂直居中的方法,費了好大勁理解了它的原理,因而就有了這篇文章。瀏覽器

這個方法是經過在父元素上添加一個高度 100%、vertical-align: middle的僞元素實現垂直居中的,效果和代碼以下:post

<div class="parent">
  <div class="child">child</div>
</div>
複製代碼
.parent {
    width: 300px;
    height: 300px;
    border: 1px solid red;
    text-align: center;
}
.child {
    background: blue;
    width: 100px;
    height: 40px;
    display: inline-block;
    vertical-align: middle;
}
.parent::before {
    content: '';
    height: 100%;
    display: inline-block;
    vertical-align: middle;            
}
複製代碼

基本概念

在深刻了解以前,先來了解一些基本概念。spa

基準元素

一行 inline 元素中,取行高最高元素的做爲基準元素。.net

行內元素的基線

咱們都知道,默認狀況下,行內元素的垂直對齊方式爲基線對齊。這裏的基線(base line)指的是英文字母「x」的下端沿: 3d

圖片來源:https://blog.csdn.net/lulujiajiawenwen/article/details/8245201code

舉個例子,下圖的兩個行內元素都是基線對齊的,紅色的線就是它們的基線: cdn

<div class="parent">
  <div class="child1">abcxyz</div>
  <div class="child2">efghij</div>
</div>
複製代碼
.parent {
  width: 300px;
  height: 100px;
  border: 1px solid blue;
}
.child1 {
  display: inline-block;
  height: 20px;
  background-color: green;
}
.child2 {
  display: inline-block;
  height: 20px;
  background-color: yellow;
}
複製代碼

行內元素垂直對齊的依據:vertical-align 屬性

行內元素是如何判斷垂直對齊的位置呢?是依據 vertical-align屬性。按照 w3school 上的解釋:該屬性定義行內元素的基線相對於該元素所在行的基線的垂直對齊方式,默認值爲 baseline。blog

深刻了解

辨別「行內元素的基線」與「行內元素所在行的基線」

再看一遍 vertical-align 的概念:該屬性定義行內元素的基線相對於該元素所在行的基線的垂直對齊方式。這裏有兩個詞組:什麼是「行內元素的基線」?什麼是「該元素所在行的基線」?圖片

毫無疑問,「行內元素的基線」就是咱們在基線中所說的:字母「x」的下端沿。咱們在一個元素裏寫一個"x",它的下沿就是這個元素的基線。get

能夠看到,元素的基線和元素的底線之間是有間距的(上圖"x"和紅色底邊之間),這部分留給"g"、"j"等字母或中文字符

那麼什麼是「該元素所在行的基線」?一句話歸納就是:所在行的基準元素在對齊時所依據的那條線。咱們把該元素所在行看成父元素,這句話代表,父元素的基線是由它的一個子元素——基準元素決定的,基準元素依據哪條線對齊,父元素的基線就是哪條線

這時咱們就明白了這兩個「基線」的區別:

  • 行內元素的基線:是它的自有屬性,當該元素沒有子元素而只有文字時,取字母"x"的下端沿
  • 行內元素的父元素的基線:來自於它的一個子元素——基準元素,基準元素依據哪條線對齊,父元素的基線就是哪條線

也就是說:若是基準元素採用中線對齊,那麼所在行的基線就是基準元素的中線;若是基準元素採用頂線對齊,那麼所在行的基線就是基準元素的頂線。

再看垂直對齊的依據與過程

有了上面的鋪墊,咱們再回過頭來看一下這句話:默認狀況下,行內元素的垂直對齊方式爲基線對齊。那麼,如何根據這句話解釋下面的兩個元素在垂直方向上的對齊過程呢?

.parent {
  width: 300px;
  height: 100px;
  border: 1px solid blue;
}
.child1 {
  display: inline-block;
  width: 50px;
  height: 100%;
  background-color: green;
}
.child2 {
  display: inline-block;
  width: 50px;
  height: 20px;
  background-color: yellow;
}
複製代碼

可能有人會說,這很簡單啊,兩個元素都沒有設置 vertical-align 屬性,那麼按照默認狀況,它們都是基線對齊,因此內部文字就都沿着紅線對齊了。

這句話錯在哪兒?錯在「都是」。正確過程應該是:基準元素按照本身的基線對齊,其他行內元素按照父元素的基線對齊:

  1. 父元素首先肯定基準元素,即最高的元素 —— child1
  2. child1vertical-align 屬性默認值爲 baseline,所以它對齊本身的基線 —— 做爲基準元素,位置並無發生變化,可是會影響父元素的基線位置
  3. 因而父元素的基線就是 child1 的基線
  4. child2vertical-align 屬性默認值爲 baseline,所以它的垂直對齊方式也是「基線對齊」
  5. 可是最重要的一點是: child2按照父元素的基線對齊,而不是按照本身的基線對齊,即 child2 的基線對齊父元素的基線

彷佛看起來兩種解釋最後都沒啥區別啊?爲何必定要這麼大費周章地講一遍對齊過程呢?如今讓咱們給 child1 添加 vertical-align: middle,想想,child2的位置在哪兒呢?

咦?給 child1 添加 vertical-align: middlechild2 就自動「垂直居中」了?!但是我沒有給 child2 設置 vertical-align: middle啊,這是爲何?

按照咱們以前的過程再分析一遍,就簡單多了:

  1. 父元素首先肯定基準元素,即最高的元素 —— child1
  2. child1 此次採用 vertical-align: middle 中線對齊 —— 做爲基準元素,位置並無發生變化,可是會影響父元素的基線位置
  3. 因而父元素的基線就是 child1 的中線
  4. child2vertical-align 屬性默認值爲 baseline,所以它的垂直對齊方式也是「基線對齊」
  5. child2 按照父元素的基線對齊,因此就是它的基線要對齊 child1 的中線

那這裏咱們又要思考,child2 真的垂直居中了嗎?答案是沒有。由於咱們說「 child2 的基線對齊的是 child1 的中線」,因此 child2 並無垂直居中,而是在中部靠上一點點的位置。

如今咱們給 child2 添加 vertical-align: middle,會發現它降低了一點點,這時候它就真正的垂直居中了:

咱們再分析一下這個過程:

  1. 前三步都同樣:父元素的基線是 child1 的中線
  2. child2vertical-align 屬性爲 middle,採用中線對齊,因此就是它的中線對齊父元素的基線,又或者,至關於它的中線對齊 child1 的中線

總結

到這時,相信你對於瀏覽器如何實現垂直對齊,已經有一個較爲深刻的理解了。你能夠修改 child1child2vertical-align 屬性爲其餘值(suptop、...),看看會發生什麼,並試着用以上過程解釋一下緣由。

  1. 父元素的基線 === 基準元素的 vertical-align 屬性對應的線
  2. 每一個行內元素將本身 vertical-align 屬性對應的線對齊到父元素的基線

案例原理

僞元素的插入位置

首先,before 僞元素渲染在父元素的全部子元素以前,after 僞元素插入在父元素的全部子元素以後。也就是說僞元素和子元素是同級的。

原理

回到咱們文章開頭所說的案例,原理呼之欲出:利用content: ''; height: 100% 獲得一個寬度爲 0 的僞元素,即它不會顯示出來;高度 100%,因此它最高,是所在行的基準元素;利用 vertical-align: middle 將父元素的基線設置爲僞元素的中線,而後其餘行內元素採用中線對齊時,天然就是要對齊僞元素的中線了。而僞元素的高度爲 100%,因此它的中線就是整個父元素的中線,這就實現了其餘行內元素的垂直居中。

我對底層原理的猜測

從編譯原理的角度出發,我這樣理解上面的過程:

瀏覽器在解析 CSS 的時候,對於一個行內元素:

  • 若是這個行內元素沒有任何子元素,即只有文字或是一張圖片,那麼它的 vertical-align 屬性是一個固有屬性
  • 這個行內元素的父元素的基線是一個綜合屬性,歸約而得:它先找到本身全部子元素裏最高的那個子元素,而後取它的 vertical-align 屬性對應的線做爲本身的基線

而後把全部的行內元素,依據 vertical-align 屬性,對齊到父元素的基線上。

這也解釋了爲何設置基準元素的 vertical-align 屬性時,基準元素位置不變,由於父元素的基線原本就是根據它的 vertical-align 屬性值取的

結束語

以上就是我對 vertical-align 和基線的理解,歡迎各位大佬批評指正。

相關文章
相關標籤/搜索