Vertical-Align的理解
Vertical-Align
這是一個非常困擾人的屬性。
CSS對於將元素在垂直方向上對齊提供了很多方法。
取值:
用float解決:
讓元素的頂端對齊而且需要手動清除浮動。 float只能是讓頂端對齊了。
用postion:absolute解決
絕對定位讓元素脫離了正常的文件流,這些元素不會再影響周圍的元素。 在元素的padding marin固定的情況下,一點小的改變都很有可能對佈局造成影響。
vertical-align解決佈局問題
使用這個屬性進行佈局是一種hack行為, 因為它本來不是用於這個目的的。 它用在文字和 與文字相鄰元素的垂直方向上對齊問題!
你可以使用這個屬性在不同上下文中對元素進行靈活的,細粒度的排布。 元素的尺寸無需知道,元素處理normal flow中。 因此元素的變化會影響到周圍的元素,使得vertical-align 是非常有價值的排布方案的選擇。
vertical-align的奇特之處
Vertical-align有時候會變的面目猙獰。它似乎有一些謎一樣的規則。舉例來說,有時候你改變了Vertical-align的值,但是該元素垂直方向上沒有發生改變反而別的元素改變了位置。
一些資料在談到Vertical-align這個問題的時候深入程度不夠,特別是當人們想使用這個屬性佈局的時候。這些資料更多的將精力集中在了一個誤區上,就是嘗試將元素內的一切都垂直對齊。他們給出了一下在簡單情況下的例子來解釋Vertical-align這個屬性而忽略了一些複雜奇怪的方面。
使用Vertical-align的要求
用於inline 行內元素 或者 inline-block元素。
對於inline元素
一般行內非替換元素就是指文字了。
inline-block元素 具有padding margin border width height。其中高度可能是由元素的內容決定。
行框
每個行內元素是一個挨著一個的擺放在行內,但行內元素太多的情況下,一個新行就會被創建出來,這裡就有個 line-box的概念。 它把所有內容都包裹了起來。根據行內內容不同,line-box的尺寸也會不同。
這行框內,Vertical-align屬性負責對齊一些獨立的元素。 那麼這些元素是要和誰對齊呢?
關於邊界和baseline
關於垂直對齊這個知識點來說,最重要就是涉及元素的baseline。 有時候元素的盒模型的上下邊界也會變得很重要。 下面上圖
如圖有三行文字。 行高的上下邊界是紅線。文字的上下邊界是綠色線。而藍色的線就是baseline。
左邊文字的高度與行高一致的,因此綠線和紅線重合了,中間的行高是文字大小的兩倍,右邊行高是文字大小的1/2。
行內元素的外邊界在行高的上邊緣和下邊緣這個範圍內對齊,如果行高小於文字的高度也無所謂。
inline-block元素
從左到右的三幅圖片都是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行框
行框的上邊界是: 最高元素的上邊界,下邊界是最低元素的下邊界!
W3C標準沒有定義line-box的baseline的位置,這一點讓人困惑!
原因之一:baseline的位置需要滿足 vertical-align屬性的值以及讓line-box的高度最小等條件,是一個靈活引數。
行框的baseline是不可見的。
視覺化的方法:在行的開頭新增一個字母,比如’X’,這個字母的下邊界預設就是baseline位置。也就是說,圍繞著baseline在行框中形成了文字盒(text box)。 文字盒僅僅包含非格式化的line-box的文字,文字盒的邊界是上圖中的綠線。一般來說它的高度與他的父元素的font-size相同。
因為文字盒是緊緊挨著baseline的,如果baseline的位置發生變化,文字盒(strut)的位置也會變化。
- 有一個區域叫行框(line-box),垂直方向上的對齊都是發生在這個區域裡面的,它有baseline,有文字盒,有上下邊界。
- inline元素也有baseline和上下邊界,inline元素是需要對齊的物件。
BTW ,一個有趣的事情值得謹記:
使用百分數的時候:
- vertical-align的值是相對於line-height的值來取的。 比如line-height:15px; vertial-align:10%; 就是 15*10%
- 而對於line-height卻是相對於Font-Size來取的。 同上。
Vertical-align屬性的值
這是Vertical-align 幾個取值的效果。
這個屬性到底怎麼起作用?
我想對齊一個icon和文字。 僅僅使icon的vertial-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>
下面給出上圖的輔助線版本
原因是左面的文字根本就沒有發生過對齊行為,它還是對齊與行框的baseline。 而Vertical-align對齊的點時baseline加上 半個x的距離(half of the x-height)。 因此文字最高點高出了icon的高度。
而右面是,對齊於一箇中點,文字的baseline下移了,位於行框的baseline下方。 結果很好達到了icon和文字對齊的效果!
行框的baseline的移動問題
這是一個Vertical-align的坑,line-box中的所有元素都會影響到baseline的位置。
假設,一個元素按某種方式垂直對齊了,但是這種對齊方式會引起baseline的移動,又因為大部分的垂直對齊方式(除了top和bottom)和baseline有關,因此這個元素的垂直方向對齊的行為會引起該line-box內其他元素位置的調整。
下面還是一些例子:
一個很高的元素,高度佔滿了整個line-box,那麼vertical-align對它其實沒有影響的,在它的top和bottom之外沒有空間讓其移動。
但是為了滿足它的vertical-align的值,行框的baseline就會發生移動,
- 左邊的高元素取值為 text-bottom(綠線)
矮元素取值為baseline(藍線) - 右邊的高元素取值為text-top(綠色)
矮元素的取值為baseline(baseline跳上來了)
text-top:將元素行內框的頂端與父元素內容區的頂端對齊。
text-bottom:將元素行內框的底端與父元素內容區的底端對齊。
top:將元素行內框的頂端與包含該元素的行框的頂端對齊
bottom:將元素行內框的底端與包含該元素的行框的底端對齊
<!-- 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>
inline元素下方可能會有一點空隙
下面給出一個例子,如果嘗試將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>
總結和注意:
行框line-box的高度
定義是行內框的最高點和最低點的最小框。
行框的上邊界位於最高行內框的上邊界,底邊放在最低行內框的下邊界。
所以說,line-box行框的具體高度要取決於組成元素相互之間如何對齊~ vertical-align!
這種對齊往往很大程度上依賴於基線落在各元素中的哪個位置! (匿名文字也有他的基線),因為這個位置確定了其行內框如何擺放。
行內框
inline-box 的高度, 就是line-height決定的,這個行高設定的是行內框的高度而已。它是對應一個元素而言的。 而行框是對應這一行的若干個元素而言的!!!!!
補充vertical-align:middle
僅僅與其父元素有關。 跟文字框無關。
也就是說 vertical-align是個獨立的個體,與後面的line水平的元素沒有必然的聯絡。
無論它是什麼都不影響文字在box中的位置。但是對齊的方式的不同,會影響元素本身的baseline~ 這個卻是需要注意的。