前言:
最近在切頁中,我想實現左邊一個類似下拉選框,且不允許輸入,右邊有一段垂直居中的文字描述的效果。我對文字用的是p標簽。其實可以用個i/b/em等其他行內標簽,同時也具有一定語義,做為強調提示,(當時事實證明用行內標簽問題一樣存在)。最后我的問題出現了。一個設置了overflow:hidden 的inline-block元素旁邊的文字與邊框的下邊放佛是對齊的。因為vertical-align屬性的默認值時baseline,同是文字又只有一行那么它們的baseline應該是對齊的啊!!
當修改元素的vertical-align屬性為baseline以外的其他值時可以看到文字相對邊框的垂直位置發生了變化。初步能確定是跟對齊方式有關,並且是由於基線(baseline)的位置發生了變化而不再是原來的以x的下邊線做為基線了。那么是什么原因造成位置的偏移呢?經過測試,發現是overflow:hidden的這個屬性影響了inline-block元素baseline的位置。那么overflow:hidden的inline-block元素的baseline怎樣設置的呢?請繼續往下讀......
問題描述:
overflow:hidden怎樣影響inline-block的baseline的位置。導致文字不與inline-block的文字的對齊,而是向下偏移。

化繁為簡,代碼如下,效果運行請看demo。
html結構
<div class="div1"> 我是div1 </div> <div class="div2"> 我是div2 </div>
css 樣式
.div1 ,
.div2 {
display: inline-block;
}
.div1 {
width: 180px;
height: 40px;
line-height: 40px;
overflow: hidden;
border: 1px solid #000;
}

div2和左邊的框中間沒對齊。 默認對齊方式是baseline.
原因:
vertical-align的默認值是baseline。當div1 設置了屬性overflow:hidden后,baseline會設置在bottom margin的邊緣。詳情戳css規范。
規范的截圖:

翻譯:'inline-block'(盒)的基線是它的最后一個常規流中的行盒的基線,除非它沒有流內行盒或者它的'overflow'屬性的計算值不為'visible',此時基線是bottom margin邊。
所以div2的文字和div1的下邊框對齊。
注意:如果元素內部只有脫離常規流的行盒,如被設置了float 除了none以外的值,position為fixed和absolute,也會出現同樣的情況。demo
解決方案:
方案1.將設置了overflow:hidden的元素 的垂直對齊方式設置為vertical:middle;將該盒的豎直中點與父級元素的baseline對齊。demo2.

此方案需要寫的代碼少,當它周圍有其他元素的時候,也能解決。 兼容問題,在支持inline-block的瀏覽器中都支持。想要ie 6,7兼容可以觸發haslayout,並將元素用ie6、7的hack設為inline盒模型。使其表現出inline-block的特性。
代碼如下:
.div1,
.div2 {
display: inline-block;
*display: inline; /*ie7及以下瀏覽器 以內聯盒模型渲染*/
*zoom: 1; /*觸發ie的haslayout*/
}
.div1 {
width: 180px;
height: 40px;
line-height: 40px;
overflow: hidden;
border: 1px solid #000;
vertical-align: middle;
}
方案2. 稍微麻煩點,對受影響的另一個inline-block的元素處理,讓它的line-height和div1的height相同。並且讓自己的垂直對齊方式為vertica-align:middle; demo3
.div1,
.div2 {
display: inline-block;
*display: inline; /*ie7及以下瀏覽器 以內聯盒模型渲染*/
*zoom: 1; /*觸發ie的haslayout*/
}
.div1 {
width: 180px;
height: 40px;
line-height: 40px;
overflow: hidden;
border: 1px solid #000;
vertical-align: middle;
}
.div2 {
line-height: 40px;
vertical-align: top;
}
此方法,只是讓它看起來在旁邊盒子的垂直中點位置,且如果旁邊的元素比較多,要為這些元素一一設置屬性。不建議使用。
延伸問題:
如果inline-block元素旁邊的是inline元素,有同樣的影響嗎?
答案是 yes ,請看demo4,原因也是同上。
關於baseline 怎么確定,規范上沒有具體定義,user agent自己規定。
以下摘自w3c規范
如內聯格式化上下文節所述,用戶代理把內聯級盒排列在一個行盒的垂直堆疊里。行盒的高度由下列規則決定:
- 計算行盒中每個內聯級盒的高度時,對於可替換元素,inline-block元素和inline-table元素,這個值就是其margin box的高度;對於內聯盒,這個值是其'line-height'(見“計算height與margin”和“行距(Leading)與半行距”中的內聯盒的高度)
- 內聯級盒是根據其'vertical-align'屬性豎直對齊的。如果它們是'top'或者'bottom'對齊,它們必須對齊得讓行盒高度最小化。如果這樣的盒足夠高,存在多個解,而CSS 2.1沒有定義行盒基線的位置(即,strut的位置,見下文)
- 行盒高度是最高的盒的top與最低的盒的bottom之間的距離(包括下面'line-height'中解釋的strut)
空內聯元素生成空的內聯盒,但這些盒仍然具有margin,padding,border和line height,並因此會影響這些計算,就像有內容的元素一樣。
補充 strut:對於一個內容由內聯級元素組成的塊容器元素,'line-height'指定了元素內行盒的最小高度。這個最小高度包含基線上方的最小高度和下方的最小深度,就像每個行盒以一個具有該元素的字體和行高屬性的0寬內聯盒開始。我們把這種假想盒叫做"strut"(這個名字是受TeX的啟發)。
參考資料:
https://www.w3.org/TR/CSS2/visudet.html#strut
http://blog.csdn.net/iefreer/article/details/50421025
