今天在一篇文章中無心看到一個利用僞元素實現垂直居中的方法,費了好大勁理解了它的原理,因而就有了這篇文章。瀏覽器
這個方法是經過在父元素上添加一個高度 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
屬性。按照 w3school 上的解釋:該屬性定義行內元素的基線相對於該元素所在行的基線的垂直對齊方式,默認值爲 baseline。blog
再看一遍 vertical-align
的概念:該屬性定義行內元素的基線相對於該元素所在行的基線的垂直對齊方式。這裏有兩個詞組:什麼是「行內元素的基線」?什麼是「該元素所在行的基線」?圖片
毫無疑問,「行內元素的基線」就是咱們在基線中所說的:字母「x」的下端沿。咱們在一個元素裏寫一個"x",它的下沿就是這個元素的基線。get
能夠看到,元素的基線和元素的底線之間是有間距的(上圖"x"和紅色底邊之間),這部分留給"g"、"j"等字母或中文字符
那麼什麼是「該元素所在行的基線」?一句話歸納就是:所在行的基準元素在對齊時所依據的那條線。咱們把該元素所在行看成父元素,這句話代表,父元素的基線是由它的一個子元素——基準元素決定的,基準元素依據哪條線對齊,父元素的基線就是哪條線。
這時咱們就明白了這兩個「基線」的區別:
也就是說:若是基準元素採用中線對齊,那麼所在行的基線就是基準元素的中線;若是基準元素採用頂線對齊,那麼所在行的基線就是基準元素的頂線。
有了上面的鋪墊,咱們再回過頭來看一下這句話:默認狀況下,行內元素的垂直對齊方式爲基線對齊。那麼,如何根據這句話解釋下面的兩個元素在垂直方向上的對齊過程呢?
.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
屬性,那麼按照默認狀況,它們都是基線對齊,因此內部文字就都沿着紅線對齊了。
這句話錯在哪兒?錯在「都是」。正確過程應該是:基準元素按照本身的基線對齊,其他行內元素按照父元素的基線對齊:
child1
child1
的 vertical-align
屬性默認值爲 baseline
,所以它對齊本身的基線 —— 做爲基準元素,位置並無發生變化,可是會影響父元素的基線位置child1
的基線child2
的 vertical-align
屬性默認值爲 baseline
,所以它的垂直對齊方式也是「基線對齊」child2
是按照父元素的基線對齊,而不是按照本身的基線對齊,即 child2
的基線對齊父元素的基線彷佛看起來兩種解釋最後都沒啥區別啊?爲何必定要這麼大費周章地講一遍對齊過程呢?如今讓咱們給 child1
添加 vertical-align: middle
,想想,child2
的位置在哪兒呢?
咦?給 child1
添加 vertical-align: middle
,child2
就自動「垂直居中」了?!但是我沒有給 child2
設置 vertical-align: middle
啊,這是爲何?
按照咱們以前的過程再分析一遍,就簡單多了:
child1
child1
此次採用 vertical-align: middle
中線對齊 —— 做爲基準元素,位置並無發生變化,可是會影響父元素的基線位置child1
的中線child2
的 vertical-align
屬性默認值爲 baseline
,所以它的垂直對齊方式也是「基線對齊」child2
按照父元素的基線對齊,因此就是它的基線要對齊 child1
的中線那這裏咱們又要思考,child2
真的垂直居中了嗎?答案是沒有。由於咱們說「 child2
的基線對齊的是 child1
的中線」,因此 child2
並無垂直居中,而是在中部靠上一點點的位置。
如今咱們給 child2
添加 vertical-align: middle
,會發現它降低了一點點,這時候它就真正的垂直居中了:
咱們再分析一下這個過程:
child1
的中線child2
的 vertical-align
屬性爲 middle
,採用中線對齊,因此就是它的中線對齊父元素的基線,又或者,至關於它的中線對齊 child1
的中線到這時,相信你對於瀏覽器如何實現垂直對齊,已經有一個較爲深刻的理解了。你能夠修改 child1
與 child2
的 vertical-align
屬性爲其餘值(sup
、top
、...),看看會發生什麼,並試着用以上過程解釋一下緣由。
vertical-align
屬性對應的線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
和基線的理解,歡迎各位大佬批評指正。