1. 程式人生 > >Vertical-Align的理解

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~ 這個卻是需要注意的。