1.vertical-align的五類屬性
拋開inherit這類全局屬性不談,個人把vertical-align分成五類,作者將第一類和第二類總結成線類。
(1)跟x字母打交道的線類:baseline/middle
(2)基于行框盒子邊緣的線類:top/bottom
(3)跟父級基線相關的文本類:text-top/text-bottom
(4)常用于公式的上標下標類:super/sub
(5)具體數值類:2px/2em/20%等
通常情況下,內聯元素默認都是沿著字母x的下邊緣對齊的,也就是vertical-align的默認值是baseline。但對于圖片等替換元素,往往使用元素本身的下邊緣作為基線,這一點在過去的簡陋布局中顯得非常好用,二十年前的網頁你甚至都不需要會寫CSS就可以讓讀者正常瀏覽網站內容,但是如今這些"好用的"特點會給我們的CSS布局帶來很多不便之處。下面我們通過實戰來一一測試這些屬性的表現以及利用這些表現實現一些布局方式。
2.跟x字母打交道的vertical-align:baseline/middle
前面說到了,vertical-align的默認值是baseline,也就是字母x的下邊緣,為了更好的看清x的下邊緣在哪里,我們需要借助最常用的替換元素——圖片。圖片的下邊緣通常為元素本身,我們來看字母x和圖片都基于baseline對齊會有什么表現吧。
<div>
<span>字母x</span>
<img src="../小和尚.jpg">
</div>
最終效果如下圖所示:
可以看到,表現結果跟理論相同,x下邊緣與圖片下邊緣完全持平,那么為什么中文"字母"的下邊緣沒有和x下邊緣對齊呢?沒為什么,大部分中文和部分字母的下邊緣就是低于baseline的,別問,問就是不知道。同時,你會發現,圖片的下邊緣會有4px的空隙,導致最終容器的高度多了4px,很多人第一反應就是甩鍋中文,因為中文看起來比字母x大一些,低一些,然而就算你把span標簽刪除了依舊會多出這4個像素。那么多出的4px是哪里來的呢?這里還要請出vertical-align的好朋友line-height一起來解釋這個問題。
首先line-height的默認值是normal,這個值是根據font-size和font-family計算得到的,得到的值一般會大于字母x的高度,由于高度多出來的部分由line-height計算后在文字上下均勻分布,因此你可以理解為多出來的4px是baseline到文字下邊緣的距離。因此,要解決這多出來的4px其實很簡單,修改圖片的vertical-align即可,如,讓他基于字母x的中點對齊。當然這只是理論上,你可以根據實際需求解決這個問題。
修改后的結果如下圖所示:
說完了baseline,再來聊聊middle。我不敢說很多人,我自己之前在理解vertical-align:middle的時候,認為CSS在父容器中間找了一條中線,然后讓所有的圖文基于這條中線均勻分布。事實上,這樣理解的壞處是,你會認為vertical-align需要加在父容器上,事實上vertical-align只在兩類元素內生效,就是內聯元素和table-cell元素。換句話說,vertical-align屬性只能作用在display計算值為inline、inline-block、inline-table或table-cell元素上。需要注意的是,浮動,絕對定位等讓元素塊化的操作也會讓vertical-align失效。了解了vertical-align的生效范圍后,我們來看看如何讓內聯元素在垂直方向上居中吧。依舊是剛才的例子,我們想讓圖片在固定高度的容器里用vertical-align:middle屬性垂直居中。
<div>
<span>字母x</span>
<img src="../小和尚.jpg">
</div>
<style>
div{
height: 400px;
background: rgba(0,0,0,0.1);
text-align: center;
}
img{
vertical-align: middle;
}
</style>
代碼的結果如下圖所示:
結果似乎不盡如人意,圖片并沒有垂直居中,為什么會這樣呢?其實答案已經很明顯了,vertical-align:middle屬性已經生效了,在由span和img生成行框盒子中,圖片已經基于字母x的中點垂直居中了,那么,怎么讓圖片在父級容器中居中呢?這里又要請到好朋友line-height的幫助了,只要讓line-height的值等于父容器的高度即可,當然,為了簡化代碼,我們可以去掉height的申明,讓元素保持流的特性,自動撐開容器高度。
這里圖片已經完美垂直居中了,但對于文字,可能會有一定的偏差,因為字母x的中點和許多文字的實際中點會有所偏差,這個居中屬性在文字偏大的時候就顯得明顯偏下或偏上了。因此在實際使用的過程中,不要盲目迷信vertical-align的文字居中能力。
3.基于行框盒子上下邊緣對齊的top/bottom屬性
vertical-align:top;表示當前內聯元素的頂部在垂直上邊緣對齊。在table-cell中表示元素底padding邊緣和表格行的頂部對齊。這里我們只討論內聯元素。下面我們通過一個實例來探究一下這句話的涵義。代碼如下:
<div>
<span style="font-size: 14px">14px</span>
<span style="font-size: 16px">16px</span>
<span style="font-size: 18px">18px</span>
<span style="font-size: 20px">字母x</span>
<img src="../小和尚.jpg">
</div>
<style>
div{
height: 400px;
background: rgba(0,0,0,0.1);
}
span{
vertical-align: bottom;
}
img{
vertical-align: bottom;
}
</style>
產生的結果如下,從下圖可以很明顯的看出來,內聯元素的上下邊緣對齊的邊緣是行框盒子的邊緣,不要混淆理解成了父級容器的邊緣。
4.從了解到棄用:vertical-align的文本屬性類
當你深入理解了這個屬性之后,你就會發現這個屬性很難有什么軟用。(這句話寫在開頭是為了讓你少鉆點牛角尖)
作者在給vertical-align屬性分類的時候,將baseline/middle/top/bottom分為一類,其實都是基于行框盒子進行劃分的,只是個人由其表現差異性又細分成了兩類。而文本屬性類text-top/text-bottom在垂直方向布局的時候則和行框盒子沒有多大關系了。
vertical-align:text-top 表示盒子的頂部和父級應有內容區域的頂部對齊。vertical-align:text-bottom 表示盒子的底部和父級應有內容區域的底部對齊。
內容區域指的是在默認狀態下用鼠標選中文本時的背景藍色區域,這里說的父級應有的內容區域指的是根據父級的font-size和font-family計算得到的內容區域。
有興趣的可以參考原文例子。這里就不深究這個看不到前途的屬性了。
5.簡單了解vertical-align的上標下標類屬性
HTML里有兩個標簽,sup上標,和sub下標。
sup對應的默認vertical-align:super。
sub對應的默認vertical-align:sub
這兩個屬性無需多做說明,只需看一下他的具體效果即可。
<div>
H<sub>2</sub>O<sup>[1]</sup>
</div>
<div>[1]:H<sub>2</sub>O是水的分子式</div>
由于markdown編輯器支持標簽語言,因此我們可以直接預覽最終效果如下(小提示:你可以通過瀏覽器直接檢查下面的元素看到CSS樣式)
H2O[1]
[1]:H2O是水的分子式
6.vertical-align被忽略的實用數值屬性
作者在原文中嘲諷"很多即使工作很多年的前端開發人員,可能不知道vertical-align的屬性值支持數值,更不知道支持負值",這著實讓他感到意外,沒錯我就是那個可能過一萬年都不會去知道這個值的程序員。在說明這個屬性的好處之前,先來看一個利用vertical-align“垂直居中”元素的例子。
<div style="line-height: 150px;">
<span style="vertical-align: middle;font-size: 50px">我想垂直居中,卻有些偏下</span>
<img src="../小和尚.jpg" style="vertical-align: middle;width: 50px;height: 50px">
</div>
從結果上來看,由于中文相對于x的middle表現的總體偏下,在文字偏大的時候這個問題就表現得尤為明顯了,然而圖片在這個時候表現得又比文字要好,如果是文字+圖標(icon)的格式,往往會使得文字看起總是偏下,圖標總有一些偏上,現在你知道鍋應該甩給文字了。這個時候就要請我們的vertical-align數值屬性來精確的調整文字的位置了。在不知道數值怎么設置的情況下,不如先來看看vertical-align:0,會發生什么,同時為了便于觀察,把圖片的垂直居中也改為基于基線對齊。
<div style="line-height:150px;position: relative;">
<span style="vertical-align: 0;font-size: 50px">我的vertical-align是0,x</span>
<img src="../小和尚.jpg" style="vertical-align: baseline;width: 50px;height: 50px">
</div>
這時候可以看到,vertical-align:0的表現和vertical-align:baseline的表現一模一樣!因此,vertical-align:數值,是基于baseline對齊的,為了圖片和文字最終能居中,我們當然先要保證圖片先居中(因為圖片替換屬性的特性的總能保持完全居中),再去調整文字的數值。最終調整結果如下
<div style="line-height:150px;position: relative;">
<span style="vertical-align: -10px;font-size: 50px">借助x輔助調整數值,x</span>
<img src="../小和尚.jpg" style="vertical-align: middle;width: 50px;height: 50px">
</div>
除了數值,vertical-align還支持基于line-height的百分比計算數值,個人覺得沒什么用就不說明了。
7.baseline在inline-block元素中的詭異表現
又到了CSS靈異事件的部分了,我覺得這些個靈異事件甚至可以單獨抽出一個章節來講。vertical-align屬性的默認值baseline在文本之類的內聯元素那里是指x的下邊緣,對于替換元素則是替換元素的下邊緣,看完這章應該對這兩句話有很深的印象了,但是,如果是inline-block元素,規則就要復雜一些了。
一個inline-block元素,如果里面沒有內聯元素(包括匿名內聯元素),且overflow不是visible,則該元素的基線是其margin盒子的底邊緣,否則,其基線就是其元素里面最后一行內聯元素的基線。
因為inline-block元素在實際開發中非常重要,搞清楚inline-block的詭異CSS是十分有必要的,理論看起太干,不如來個實際例子看看到底是怎么回事。
<div>
<span style="margin-bottom: 10px"></span>
<span>我有自己的內x</span>
</div>
<style>
div{
background: rgba(0,0,0,0.1);
}
span{
background: rgba(0,0,0,0.5);
display: inline-block;
width: 100px;
height: 100px;
}
</style>
可以看到第一個inline-block元素由于沒有內容導致其baseline位置發生改變,變成了margin盒子的下邊緣,而另一個inline-block元素的基線是其最后一個行框盒子的基線,在本例中,就是第二行的x字母,由于inline元素的布局是基于baseline的,因此就出現了如圖所示的"錯位"。
除了空inline-block元素和非空inline-block元素會發生錯位,行數不同的inline-block元素也會發生錯位。如下圖所示:
雖然這兩種情況都會發生錯位,但需要注意他們發生錯位的機制完全不同!
想要解決這個錯位問題其實很簡單,只要你明白錯位問題的產生的根本原因是inline-block元素和baseline有過節即可,所以inline-block元素的vertical-align可以用不基于基線的屬性,由于數值屬性也是基于基線的因此也會發生錯位問題,所以需要具體問題具體分析,我只給出一種最簡單的解決方案。如下所示
最后,給大家推薦一個前端學習進階內推交流群685910553(前端資料分享),不管你在地球哪個方位,
不管你參加工作幾年都歡迎你的入駐!(群內會定期免費提供一些群主收藏的免費學習書籍資料以及整理好的面試題和答案文檔!)
如果您對這個文章有任何異議,那么請在文章評論處寫上你的評論。
如果您覺得這個文章有意思,那么請分享并轉發,或者也可以關注一下表示您對我們文章的認可與鼓勵。
愿大家都能在編程這條路,越走越遠。