1. 什么是浮動
《精通CSS》(第3版)關於浮動的描述:
浮動盒子可以向左或向右移動,直到其外邊沿接觸包含塊的外邊沿,或接觸另一個浮動盒子的外邊沿。
浮動盒子也會脫離常規文檔流,因此常規流中的其他塊級盒子的表現,幾乎當浮動盒子根本不存在一樣。
為什么說“幾乎”?因為其他元素盒子中的文本內容會記住浮動元素的大小,並在排布時避開它,為其留出相應的空間。從技術角度來講,就是跟在浮動元素后面的行盒子會縮短,從而為浮動元素留空,造成文本環繞浮動盒子的效果。事實上,浮動就是為了在網頁中實現文本環繞圖片的效果而引入的一種布局模型。
關於包含塊的描述:
確定元素的包含塊,要看元素是如何定位的。
如果元素的定位方式為靜態定位(即不指定position
屬性的值)或相對定位,則其包含塊的邊界就計算到一個最近的父元素,該元素的display
屬性值必須能夠提供類似塊級的上下文。
默認情況下,width
、height
、margin
和padding
的值為百分比時,就以該父元素的尺寸為計算依據。
關於格式化上下文的描述:
元素在頁面上水平或垂直排布時的一套規則叫作格式化上下文。
格式化上下文又分為:
- 行內格式化上下文
- 塊級格式化上下文
先看一個例子。
<style>
.child {
width:100px;
height:100px;
}
.child1 {
background-color:red;
}
.child2 {
background-color:yellow;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child child1"></div>
<div class="child child2"></div>
</div>
div
是塊級元素,它獨占一行。現在我們使用浮動。
.child1 {
float:left;
background-color:red;
}
我們發現背景色為黃色的div
(簡稱"黃色div
")在頁面中不見了。事實上,這是由於使用了浮動的div
脫離常規文檔流,而常規流中的元素排列時當這個浮動的div
不存在一樣。
我們覆蓋黃色div
的樣式,寬度改為200px
。
.child2 {
width:200px;
background-color:yellow;
}
我們這時看到了黃色div
了,不過它看上去像是緊跟在紅色div
后面,寬度為100px
。事實上,黃色div
的寬度為200px
,其中的100px
被浮動的紅色div
擋住而已。
2. 清除浮動的幾種方法
2.1 使用clear屬性
清除浮動使用clear
屬性,《精通CSS》(第3版)關於該屬性的描述:
要阻止行盒子環繞在浮動盒子外面,需要給包含行盒子的元素應用
clear
屬性。clear
屬性的值有left
、right
、both
和none
,用於指定盒子的哪一側不應該緊挨着浮動盒子。
.child {
width:100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
.child2 {
width:200px;
background-color:yellow;
clear:left;
}
上面就是清除浮動的效果,我們終於看到了寬度為200px
的黃色div
,它沒有被浮動的紅色div
擋住了。
簡而言之,我們說clear
屬性指定元素哪一側不能出現浮動元素。紅色div
的位置已經確定,黃色div
的左邊又不能有浮動元素,因此,黃色div
渲染到了紅色div
下方。
2.2 使用:after偽類
我們可以使用:after
偽類來模擬額外的清除元素。
<style>
.child {
width:100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
.child1Wrapper:after {
content:'';
display:block;
clear:both;
}
.child2 {
width:200px;
background-color:yellow;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child1Wrapper">
<div class="child child1"></div>
</div>
<div class="child child2"></div>
</div>
沒有清除浮動時,父元素的高度塌陷為0
。
<style>
.parent {
width:200px;
padding:5px;
background-color:gray;
}
.child {
width:100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child1Wrapper">
<div class="child child1"></div>
</div>
</div>
清除了浮動之后,父元素就有高度了。
.child1Wrapper:after {
content:'';
display:block;
clear:both;
}
為什么父元素有高度了呢?這其實跟塊級格式化上下文有關系。參考閱讀:為什么"overflow:hidden"能清除浮動的影響
上述參考閱讀引出了下面將要講的overflow:hidden
。
3. overflow:hidden清除浮動的原理
<style>
.child {
width:100px;
height:100px;
}
.child1 {
float:left;
background-color:red;
}
.child2 {
width:200px;
background-color:yellow;
}
</style>
<!-- ... -->
<div class="parent">
<div class="child1Wrapper">
<div class="child child1"></div>
</div>
<div class="child child2"></div>
</div>
在浮動元素的父元素上使用overflow: hidden
。
.child1Wrapper {
overflow: hidden;
}
使用overflow: hidden
時,實際上就創建了一個塊級格式化上下文,該塊級格式化上下文決定了height:auto
(不設置height
時,其默認值為auto
)是如何計算的。
計算塊級格式化上下文的高度時,浮動元素也參與計算。因此,父元素在計算其高度時,加入了浮動元素的高度,就達到了清理浮動的效果。
參考:
- 《精通CSS》— [英] 安迪·巴德、[瑞典] 埃米爾·比約克隆德
- 為什么"overflow:hidden"能清除浮動的影響
- 清除浮動的四種方式及其原理理解