怎麼理解CSS中vertical-align這個屬性?

一:由一個題引入:未知高度的img怎麼垂直居中於div? 其中解法之一:

&

&&&

&

.wrap{width:400px; height:400px; margin:0 auto; border:1px #000 solid;}

.wrap span{display:inline-block; height:100%; width:1px; border-right:1px #f00 solid; vertical-align:middle;}

.wrap img{vertical-align:middle;}

二:問題

1:spec中對middle的解釋:Align the vertical midpoint of the box with the baseline of the parent box plus half the x-height of the parent. 怎麼也不能理解。這裡的parent box是不是就是line box??plus half the x-height of the parent又何解?

2:例題中,span和img的vertical-align:middle有且保留一個時,導致img位置變動,兩種不同位置變化怎麼解釋?兩個值都保留時就能實現img在div中的垂直居中怎麼解釋?

3:html5 dtd中div.wrap的line-h=height時,且img的vertical-align:middle(不需要span),也能使得img在div中的垂直居中,這又何解?我們知道line-height常用於單行文本的垂直居中,怎麼卻能用於img這種 inline replaced elements,但是又不像單行文本垂直居中那麼簡單,還要給img加上vertical-align:middle?


懶的敲,貼點過來

結合 CSS 2.1 規範中行內格式化上下文、行高計算、差異半差異、"line-height" 和 "vertical-align" 特性中相關說明,可以總結出行框頂邊與行框底邊位置的計算方式:

  • 每一個行內元素會產生一個行內框;
  • 行內框會在行框內橫向排列;
  • "line-height" 特性值指定了每個行內非替換元素生成的行內框的 確切 高度;行內替換元素的高度由 "height" 特性值決定;
  • 文字在行內框中垂直排列,上下空隙用半差異填補;如果字型大小大於行內框則文字從上下方向上溢出行內框,並可能滲入到其他行框內(行框是永遠不會重疊的);
  • "vertical-align" 特性值指定了每個行內框的垂直對齊方式;
  • 行框的頂邊界是這一系列垂直對齊的行內框最高的頂邊框,底邊界是最低的底邊框。
  • 行框的高度是頂邊界到底邊界的距離。

然後看看

RD1016: 各瀏覽器對常用行內替換元素的 "baseline" 位置理解不同

RD8009: IE6 IE7 IE8(Q) 中行框的頂邊與底邊位置識別有誤

RD3020: 在不同的文檔模式中,當唯一的非表單控制項類行內替換元素存在於其包容塊中時,其父框的行高並不一定會計算文本基線高度


這個答案可能是你想要的。鏈接地址:2011年9月23日 隨筆檔案

原文中主要的幾個點:

  • line-box的height由其中的inline-box元素計算,對於inline-replace元素就為其margin box的height,no-replace元素為其line-height。此時line-box會做到包圍其中所有的inline-box。其高度高於其中最高的inline-box。

  • line-box與其inline-box關係如圖:

  • line-box的baseline的計算方法:line-box中所有vertical-align:baseline(沒明顯設置,即默認也為baseline)的line-height box和margin box都參與計算。

  • middle:inline-height
    box (或 margin box)的中心對齊line
    box的baseline再上移x中心的距離(跟font-size有關,一般直覺上認為中間對中間即可)。

對於題主的這個例子:div下面有span與img,

  • 當span不存在時,img產生行內margin box,此時line-box的高度由img的height決定。line-box位置為div的左上角,此時middle相對於line-box而不是div所以不會垂直居中。

  • 在圖片前面設置span,span設置為inline-block成為inline-replace。span高度設置為100%即div的高度。此時span的height高於img。line-box高度變為span的height。
  • 由於middle的計算使用了line-box的base-line,而line-box的base-line受其中所有inline子元素的base-line影響。因此單獨設置img的vertical-align:middle其位置有偏差,需要同時設置span的vertical-align:middle才可以。top與bottom沒有這個限制。
  • 設置div的line-height等於其height,這個我估計是img產生的line-box的height繼承了父元素的line-height。而這裡line-box中只有img一個元素,其base-line與middle完全由img的vertical-align來決定。


推薦閱讀:

想從零開始學習 HTML5 和 CSS,請問有沒有比較好的建議?比如學習什麼語言,有沒有好的書或者教程推薦等等?
強調 HTML/CSS/JS 基礎的前端教程是否存在誤區?
為什麼要有js立即執行函數,存在的意義是什麼?
參加 JSConf CN 2017 是個什麼樣的體驗?
redux的state樹應該如何設計?

TAG:網頁設計 | 前端開發 | HTML | CSS | CSSReset |