開始學習前端以來,在CSS相關知識當中困擾我最多的就是Vertical-Align這個屬性。在stackoverflow上查找相關問題的時候看到了這篇文章,因而將它翻譯出來,做爲本身的一次學習筆記吧。css
在遇到將元素在垂直方向上對齊的需求時,CSS提供了多種方法,有時候我用float
解決,有時候我使用position:absolute
解決,還有時候採用的方法是手動調整margin
和padding
。
其實我並不喜歡這些解決方法,float
會讓元素的頂端對齊並且須要手動清楚浮動。絕對定位讓元素脫離了正常流,這樣這些元素就不會再影響到周圍的元素。在元素的padding
和margin
固定的狀況下,一點小的改變也頗有可能對佈局形成影響。
接下來登場的就是本文的主角了:Vertical-align
。一般來講使用這個屬性進行佈局是一種hack行爲,由於它原本並非被用於這個目的。它用在文本和與文本相鄰元素的垂直方向上的對齊問題。然而,你也可使用Vertical-align
在不一樣的上下文中對元素進行靈活的,細粒度的排布。元素的尺寸無需知曉,元素任然處於正常流當中,所以元素的變化會影響到周圍的元素,這使得Vertical-align
是很是有價值的排布方案的選擇。html
Vertical-align
有時候會變的面目猙獰。它彷佛有一些謎同樣的規則。舉例來講,有時候你改變了Vertical-align
的值,可是該元素垂直方向上沒有發生改變反而別的元素改變了位置。
一些資料在談到Vertical-align
這個問題的時候深刻程度不夠,特別是當人們想使用這個屬性佈局的時候。這些資料更多的將精力集中在了一個誤區上,就是嘗試將元素內的一切都垂直對齊。他們給出了一下在簡單狀況下的例子來解釋Vertical-align
這個屬性而忽略了一些複雜奇怪的方面。前端
Vertical-align
被用於垂直對齊inline
元素,也就是display
值爲inline
和inline-block
的元素。inline-table
的元素不在本文的討論範圍內。inline
元素基本上值得就是文本inline-block
元素就像它的名字同樣,同時具有inline
元素和block
元素的特色,這樣的元素有padding,margin,border,width,height
。其中高度有多是由元素的內容決定的。inline
元素一個挨着一個的擺放在行內,當行內元素太多的狀況下,一個新行會被建立出來,這些行也叫作line--box
。它將行內的全部內容都包裹了起來。根據行內內容的不一樣,line-box
的尺寸也會不一樣,在接下來的圖裏面,紅線表明了line-box
的上下邊界
在這些line-box
內,Vertical-align
屬性負責對齊一些獨立的元素。那麼,這些元素是要和誰對齊呢?ide
對於垂直對齊這個知識點來講最重要的就是涉及元素的baseline。有時候元素的盒模型的上下邊界也會變的很重要。下面上圖
如圖所示有三行文字。行高的上下邊界是紅線。文字的上下邊界是綠色的線,藍色的線就是baseline了,左邊文字的高度與行高是一致的,所以綠線和紅線重合了,中間的行高是文字大小的兩倍,而在右邊,行高是文字大小的二分之一。
行內元素的外邊緣在行高的上邊緣和下邊緣這個範圍內對齊,若是行高小於文字的高度也無所謂。關於baseline的定義仍是直接給出標準的連接佈局
從左到右的三幅圖片都是inline-block
元素,不一樣的是,左面包含着沒有脫離正常流的內容c,中間的除了沒有脫離正常流的內容之外還加了overflow:hidden
,右面的沒有內容可是內容區還有高度。紅線表明了margin-box
的邊界。黃色表明的是border,綠色的是padding,藍色的是content,藍色的線表明的仍是baseline。inline-block
元素的外邊緣就是margin-box
的邊緣。inline-block
元素的baseline的位置要看該元素有沒有處於正常流以內的內容。
(1)在有處於正常流內容的狀況下,inline-block
元素的baseline就是最後一個做爲內容存在的元素的baseline,這個元素的baseline的肯定就要根據他自身來肯定了。
(2)在overflow屬性不爲visible的狀況下,baseline就是margin-box的下邊界了。
(3)第三種狀況下baseline仍是margin-box的下邊界。學習
關於line-box的圖上面已經給過了,此次我將文字部分高亮顯示。line-box的上邊界與最高元素的上邊界對齊,下邊界與最低元素的下邊界對齊。
W3C標準中並無定義line-box的baseline的位置。這一點很讓人困惑,baseline的位置須要知足vertical-align屬性的值以及讓line-box的高度最小等條件,是一個很靈活的參數。
line-box的baseline是不可見的,可是能夠很輕鬆的將它可視化出來,在行的開頭添加一個字母,好比'x',這個字母的下邊界默認就是baseline的位置。圍繞着baseline在line-box中造成了文字盒。文字盒能夠被認爲是沒有和任何元素對齊的line-box中的inline元素,它的告訴與它的父元素的font-size的值相同。所以,文字盒僅僅包含非格式化的line-box的文本,文字盒的邊界由綠線來表示。由於文字盒是緊挨着baseline的,因此baseline的位置發生變化的話,文字盒的位置也會跟着改變(這裏所說的文字盒在標準中被叫作strut)。
總結起來的話有如下兩點:spa
有關Vertical-align各個取值的說明讀者仍是上MDN看吧。也能夠看看天鑲大神的博客上的文章.net
我想將一個icon與文字對齊僅僅使icon的vertical-align屬性的值設置爲middle彷佛不能產生使人滿意的結果,例子以下圖翻譯
<!-- 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>
下面給出上圖的輔助線版本
緣由就是左面的文字根本就沒有發生對齊行爲,它仍是對齊於line-box的baseline。而vertical-align對齊的點是baseline加上半個x的距離(half of the x-height)。所以文字的最高點超過了icon的高度。
而右面的例子,文字與icon都對齊於一箇中點,文字的baseline稍微下移,位於line-box的baseline的下方。結果是很好的達到了icon與文字對齊的效果。3d
這是一個Vertical-align的坑,line-box中的全部元素都會影響到baseline的位置。假設,一個元素按某種方式垂直對齊了,可是這種對齊方式會引發baseline的移動,又由於大部分的垂直對齊方式(除了top和bottom)和baseline有關,所以這個元素的垂直方向對齊的行爲會引發該line-box內其餘元素位置的調整。
下面仍是一些例子
<!-- 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設置爲bottom或者是top也會讓baseline發生移動。這很奇怪,由於這時候應該就沒baseline什麼事兒了。
<!-- 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裏面,而且設置vertical-align的值讓line-box的baseline移動。在知足vertical-align數值對齊的條件下,line-box的高度會自我調整,如左面的圖。再增長第三個元素,第三個元素若是由於其vertical-align的設置不會超過line-box的邊緣的話,它是不會影響到line-box的高度和baseline的位置的,若是它會超過line-box的邊緣,那麼line-box的高度和baseline的位置也會進行調整。在第二種狀況下,另外兩個元素的位置發生了下移。
<!-- 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>
下面給出一個例子,若是嘗試將li元素在垂直方向上進行對齊的話在,這個現象很是常見。
<ul> <li class="box"></li> <li class="box"></li> <li class="box"></li> </ul> <style type="text/css"> .box { display: inline-block; /* size, color, etc. */ } </style>
正如你所見,li元素是對齊baseline的,baseline的下方會給字母的一部分留出空間,所以會產生一個空隙。解決方案就是改變line-box的baseline的位置,好比將這些li這是爲vertical-align:middle
<ul> <li class="box middle"></li> <li class="box middle"></li> <li class="box middle"></li> </ul> <style type="text/css"> .box { display: inline-block; /* size, color, etc. */ } .middle { vertical-align: middle; } </style>
inline元素之間的空隙形成佈局效果與理想狀態發生誤差
這主要是由於inline元素自己的緣由,可是由於若是要讓vertical-align的值產生做用的話,inline元素是必備要求,所以瞭解一點也不錯嘛
這個空隙來源於inline元素之間的空格,全部的inline元素之間的空白都會變成一個空格。若是你想讓inline元素在水平上緊挨着,設置它們的寬度是不行的。由於之間存在空隙,因此行的寬度不夠放下兩個inline元素。一行會被破壞爲兩行。解決方案以下圖的右側
<!-- left mark-up --> <div class="half">50% wide</div> <div class="half">50% wide... and in next line</div> <!-- right mark-up --> <div class="half">50% wide</div> <!-- --> <div class="half">50% wide</div> <style type="text/css"> .half { display: inline-block; width: 50%; } </style>
兩個建議,若是vertical-align屬性不起做用,那麼問問本身: