今天看到一個問題:javascript
兩個div 都設置 display:inline-block,正常顯示;可是在第二個div中加一個塊級元素或者內聯元素,顯示就變了個樣,爲何?css
<meta charset="utf-8"/> <style> div{ width: 100px; height: 100px; border:1px solid red; display: inline-block; } .align{ /* vertical-align: top;*/ } </style> <body> <div> </div> <div class="align">爲何?</div> </body>
解決方案就是給第二個div加上:vertical-align:top。html
關於vertical-align和基線我知道一點,可是這個問題我沒能答出,因此學習總結分享一下。java
w3c有一段相關信息以下:react
'vertical-align'
Value: baseline | sub | super | top | text-top | middle | bottom | text-bottom | <percentage> | <length> | inherit
Initial: baseline
Applies to: inline-level and 'table-cell' elements
Inherited: no
Percentages: refer to the 'line-height' of the element itself
Media: visual
Computed value: for <percentage> and <length> the absolute length, otherwise as specified
能夠看到vertical-align影響inline-level元素和table-cell元素垂直方向上的佈局。根據MDN描述,vertical-align對::first-letter和::first-line一樣適用。chrome
適用於:json
inline水平的元素segmentfault
'table-cell'元素async
因此默認狀況下,圖片,按鈕,文字和單元格均可以用vertical-align屬性。ide
取值:
vertical-align: baseline|length|percentage|sub|super|top|middle|bottom|text-top|text-bottom|initial|inherit;
字母x的下邊緣(線)就是基線。不是字母s
之類下面有尾巴的字母
基線甚至衍生出了:
一、inline-table元素的baseline是它的table第一行的baseline。
二、父元素【line box】的baseline是最後一個inline box 的baseline。
三、inline-block元素的baseline肯定規則
上圖描述:
上圖中從左到右都是line-block元素,紅線表明margin-box的邊界,藍線表明baseline;黃色爲border,綠色爲padding,藍色爲content。
左邊元素包含着沒有脫離正常流的內容c,中間元素除了沒有脫離正常流的內容c外還增長了overflow:hidden,右邊元素沒有內容,可是內容區有寬高。
分析圖中各類狀況inline-block元素的baseline:
上圖左圖,inline-block元素有處於正常流的內容,根據規則1,因此inline-block的baseline就是最後一個做爲內容存在的元素的baseline,也就是內容c的baseline,而c的baseline根據自身定,就是圖中藍色。
上圖中圖,inline-block元素overflow:hidden不爲visible,根據規則2,該inline-block元素baseline就是inline-block元素的margin-box的下邊界了,即圖中藍線。
上圖右圖,inline-block元素沒有內容,根據規則2,因此其baseline爲margin-box的下邊界,即藍線。
舉例:
<style type="text/css"> .ctn-block{ display: block; background-color: #bbb; line-height: 200px; font-size: 50px; } .ctn-block .child1{ display: inline-block; width: 100px; height: 100px; margin:10px 0; vertical-align: baseline; background-color: aliceblue; } </style> <div class="ctn-block"> <div class="child1"></div> <span>Gg</span> </div>
分析:
父元素.ctn-block的base-line是Gg的baseline,
inline-block元素由於沒有內部line box,也沒有設置overflow:visible,因此其baseline是底margin邊界。
將子元素盒子的baseline與父盒子的baseline對齊。
將元素盒子的垂直中點與父盒子的baseline加上父盒子的x-height的一半位置對齊
這裏元素盒子的垂直中點容易肯定,父盒子的baseline也好肯定,可是x-height要進行計算獲得,這個x-height就是字母x的高度。
將盒子的頂端(margin-top邊界)與父盒子的文本區域頂端對齊
審查盒子看到margin-top的頂端。
審查文本,看到藍色區域的上邊界就是文本區域頂端。
最終效果就是盒子的頂端與父盒子文本區域頂端對齊。
將盒子的底端(margin-bottom邊界) 與父盒子的文本區域底端對齊
和text-top相似,不過將子元素的margin-bottom和文本區域的下邊界對齊。
將子元素盒子的baseline下降,到適當的父盒子的下標位置
子元素的baseline已經肯定了,就是margin-bottom下邊界,可是父盒子的下標位置太很差理解。。。首先須要瞭解下標這個概念,咱們能夠經過<sub>標籤爲文字添加下標,將<span>中的內容修改成Gg<sub>Gg</sub>,就會有以下效果。
這裏就是將元素的margin-bottom下邊界和下標的baseline對齊。
將元素盒子的baseline升高,到適當的父盒子的上標位置。
與sub對應,super提高到上標內容的baseline處,首先經過<sup>標籤建立上標。
百分比:升高(正值)或下降(負值)子元素盒子,具體的升高/下降數值由父盒子的line-height的值乘以百分比計算得出。若是百分比爲0%,就和vertical-align:baseline同樣。
這個是至關好理解的,就至關於子元素盒子的baseline升高或下降,具體數值爲百分比乘以父盒子的line-height。
本例中,父盒子的line-height爲200px,因此設定25%,元素應該上移50px。
並非很直觀,給它加上一個transform: translate(0, 50px);【相對下移50px】,它又移到那個熟悉的位置了。
升高(正值)或下降(負值)子元素盒子。值爲升高/下降的距離,若是爲0,和vertical-align:baseline同樣。
以咱們最經常使用的px做爲單位,設定vertical-align:50px,效果就和上面百分比爲25%(200px*25%=50px)同樣了,不作例子了。
當vertical-align設置爲top和bottom時,其就不是按照baseline進行定位了,而是根據line box進行定位。子元素盒子的頂部和底部也就是其上下margin外邊界。
將子元素盒子的頂部和其所在的line box頂部對齊
因爲vertical-align:top將會讓子元素盒子頂部與line box頂部對齊,而若是line box高度小於子元素高度,line box將會被撐開。咱們先用一個高度較高的元素撐開line box,而後看看效果:
能夠看到,big子元素撐開了line box,而child1的margin-top外邊界緊貼在line box的頂端。
將子元素盒子的底部和其所在的line box底部對齊
和top相似,因爲big用於撐開line box,能夠沒必要修改其vertical-align的值,僅修改child1爲vertical-align:bottom,效果:
例子:嘗試將li元素在垂直方向上進行對齊的話,這個現象很是常見
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style type="text/css"> ul{ background-color: bisque; } .box { display: inline-block; width: 100px; height: 100px; background-color: aliceblue; /* vertical-align: middle;*/ } </style> </head> <body> <ul> <li class="box"></li> <li class="box"></li> <li class="box"></li> </ul> </body> </html>
由於li元素默認vertical-align:baseline,而baseline的下方會給字母的一部分留出空間,所以會產生一個空隙,要產生理想的效果,解決方案就是改變line box的baseline位置,好比將這些li設置爲vertical-align:middle。【tip:加一個x效果更明顯】
li元素的水平空隙是由於換行引發的,這個換行會變成一個空白,這個空白會被解析爲DOM中的文本節點。好比像下面醬紫的代碼。
<ul> <li class="box"></li><li class="box"></li> <li class="box"></li> </ul>
效果以下:由於前2個li之間沒有空白,而2和3個li之間有空白。
可是上面的代碼可讀性太差,也不美觀,通常這樣寫
<ul> <li class="box"></li><!-- 註釋去空格 --><li class="box"></li> <li class="box"></li> </ul>
咱們用一個註釋節點代替空白(文本節點),而註釋節點渲染的時候是不渲染的。瞭解更多DOM中的節點類型,可看個人另外一篇文章《DOM》。
如今有三個inline-box塊,高度分別爲100px,200px,300px,想讓高度爲100px的塊垂直居中,因而寫出了以下代碼:
<style type="text/css"> .ctn-block{ background-color: #bbb; } .ctn-block .child { display: inline-block; width: 100px; background-color: aliceblue; } .ctn-block .child-1 { height: 100px; /* vertical-align: middle;*/ } .ctn-block .child-2 { height: 200px; } .ctn-block .child-3 { height: 300px; } </style> ---------------------------------------------- <div class="ctn-block"> <div class="child child-1"></div> <div class="child child-2"></div> <div class="child child-3"></div> </div>
給中間div加上vertical-align:middle,效果變爲上圖二的樣子——child-1元素下移了,可是卻沒有居中。
從上面能夠指定,vertical-align:middle的定位方式是:將子元素盒子的垂直中點與父盒子的baseline加上父盒子的x-height的一半位置對齊。
子元素盒子的中點很好算,而父盒子的baseline加上父盒子的x-height一半位置又是什麼呢?
首先計算父盒子的baseline:三個子元素的baseline走在一條直線上,就是child-2和child-3的底部。
而後加上父盒子的x-height:因爲chrome下默認font-size是16px,而font-family:sans-serif,因此x-height的一半大概是3-4px,綜上,按照以下方式對齊:
一種方式是將最高的元素設爲vertical-align:middle。
而後將想要居中的也設定爲vertical-align:middle,其餘的根據須要設定vertical-align:top/bottom。
原理有點抽象:
首先明確一點:最高元素設定爲vertical-align:middle後,這個元素對於line box來講,baseline就是其中線。
其餘元素設置vertical-align:top/bottom後,它們不影響line box的baseline,因此再將須要設定垂直居中的元素也設定爲vertical-align:middle,它們的baseline必然在最高元素的baseline之上,因此會會被強制下移,進行居中。
.ctn-block .child-1 { height: 100px; vertical-align: middle; } .ctn-block .child-2 { height: 200px; vertical-align:top; } .ctn-block .child-3 { height: 300px; vertical-align: middle; }
爲父元素設定一個僞元素::after,其高度爲父元素的高度,display:inline-block,將其設定爲vertical-align:middle便可撐開line box,同時line box的baseline爲父元素高度一半的位置。而後設定子元素vertical-align:middle,便可實現居中。
考慮兼容性的話,這裏須要使用一些hack,因爲IE8不支持::after僞元素,因此須要一個span來替代。而display:inline-block亦須要hack。
個人《未知寬高圖片垂直居中》一文中就用到這種方案。
<style type="text/css"> .pop-viphead-nologinbox { width:500px; } .pop-viphead-nologin-icon { display:inline-block; width: 14px; height: 14px; background: url("images/not_login_tip_ico.png") no-repeat; } .pop-viphead-nologin-txt { display: inline-block; color: #333; font-size: 12px; margin-left:2px; } .pop-viphead-nologin-btn { display: inline-block; margin-left: 3px; } .pop-viphead-nologin-btn a { display: block; width: 76px; height: 25px; line-height: 25px; color: #fff; text-align: center; background-color: #00adee; border-radius: 1px; font-size: 12px; } </style> <div class="pop-viphead-nologinbox"> <div class="pop-viphead-nologin-icon"></div> <span class="pop-viphead-nologin-txt">您尚未登陸哦!</span> <div class="pop-viphead-nologin-btn"><a href="javascript:;" j-delegate="login">當即登陸</a></div> </div>
我想讓左邊ico和文字,按鈕都對齊。
.pop-viphead-nologin-icon,.pop-viphead-nologin-txt,.pop-viphead-nologin-btn{ vertical-align: middle; }
參考資源:
baseline:
若是想要了解更多關於baseline的詳細的信息,能夠參照W3C標準css-inline的baseline部分
更多關於baseline的肯定方式能夠參照W3C標準css-align的baseline-rules部分
vertical-align:
天鑲大神
垂直居中之vertical-align詳解CSS佈局之vertical-align
w3c line-height和vertical-align
這篇文章在草稿箱呆了快2年了,從新整理了一下,發佈出來。
本文做者starof,因知識自己在變化,做者也在不斷學習成長,文章內容也不定時更新,爲避免誤導讀者,方便追根溯源,請諸位轉載註明出處:http://www.cnblogs.com/starof/p/4512284.html有問題歡迎與我討論,共同進步。