對於height
屬性,如果父元素height
為 auto
,只要子元素在文檔流中(即position
不等於fixed
或者absolute
),其百分比值完全就被忽略了。這是什么意思呢?首先來看個例子,比如,某小白想要在頁面插入一個<div>
,希望滿屏顯示黑色背景,就寫了如下 代碼:
<!DOCTYPE html>
<html lang="en">
<head>
<title>黑色主題</title>
<style>
.box {
width: 100%; // 這是多余的
height: 100%; // 這是無效的
background: #000;
}
</style>
</head>
<body>
<div class="box"></div>
</body>
</html>
然后他發現這個<div>
高度永遠是 0,哪怕其父級<body>
塞滿了內容也是如此。事實上,他需要加上這樣的設置才行:
html, body {
height: 100%;
}
並且僅僅設置<body>
也是不行的,因為此時的<body>
也沒有具體的高度值:
body {
/* 子元素 height:100%依舊無效 */
}
只要經過一定的實踐,我們都會發現對於普通文檔流中的元素,百分比高度值要想起作用,其父級必須有一個可以生效的高度值!但是,怕是很少有人思考過這樣一個問題:為何父級沒有具體高度值的時候,height:100%
會無效?
網上有種觀點認為,如果父元素height: auto
,又要讓子元素height:100%
生效的話,會使得布局進入一種死循環。比如下面的代碼:
<style>
.child1 {
height: 100px;
}
.child2 {
height: 100%;
}
</style>
<div class="parent">
<div class="child1"></div>
<div class="child2"></div>
</div>
他們的推理大概如下:
parent 元素的高度默認為auto
。首先,child1的高度為100px
, 這時候 parent 的高度也會等於100px
, 然后因為 child2 的height: 100%
,所以它的高度會等於 parent 的高度也變成了100px
,這時候 child1 + child2 的高度是200px
,導致 parent 的高度也變成了200px
, 接着 child2 因為height: 100%
,高度也要等於 parent 的高度,所以變成了200px
,然后就會陷入無限死循環了。
這個推論看上去好像有理有據 ,但是,實際上是個謬論來着。為什么這樣說呢?要明白其中的原因要先了解瀏覽器渲染的基本原理。首先,先下載文檔內容,加載頭部的樣式資源(如果有的話),然后按照從上而下、自外而內的順序渲染 DOM 內容。套用本例就是,先渲染父元素 parent,后渲染子元素 child1 , 最后渲染子元素 child2 ,是有先后順序的。因此,當渲染到child2
的時候,父元素高度已經固定為 100px 了。高度不夠怎么辦?溢出就好了,overflow 屬性就是為此而生的。
記住,瀏覽器渲染規則是:靜態渲染,一次到位。
真實的原因是:如果包含塊(即父元素)的高度沒有顯式指定(即高度由內容決定),並且該元素不是絕對定位,則計算值為auto(這是計算值,是指渲染之后解釋的值,並不是我們設置height: auto
所指的值)。一句話總結就是:因為解釋成了 auto。要知道,auto 和百分比計算,肯定是算不了的:
'auto' * 100/100 = NaN
此時,他們的計算結果是NaN,這就是父元素沒有設置高度時,子元素高度百分比不生效的原因了。
那有什么辦法讓高度百分數生效呢?有兩種辦法。
(1)設定顯式的高度值。例如,設置height:600px
,或者可以生效的百分比值高度。例如,我們比較常見的:
html, body {
height: 100%;
}
(2)使用絕對定位
為什么使用絕對定位就可以了呢?因為會使元素具有“格式化高度”。那什么又是格式化高度?
格式化寬度/高度僅出現在“絕對定位模型”中,也就是出現在position
屬性值為 absolute
或 fixed
的元素中。當left/top
或top/bottom
對立方位的屬性值同時存在的時候,元素的寬度/高度表現為“格式化寬度/高度”,其寬度/高度相對於最近的具有定位特性(position
屬性值不是static
)的祖先元素計算。
回到開頭提到的盒子,小白設置height
不生效的問題,如果用絕對定位方法實現,可以設置他的父元素body
為絕對定位,代碼如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>黑色主題</title>
<style>
body {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.box {
width: 100%;
height: 100%;
background: #000;
}
</style>
</head>
<body>
<div class="box">
</div>
</body>
</html>