我們都知道"overflow:hidden"可以溢出隱藏,即當內容元素的高度大于其包含塊的高度時,設置該屬性即可把內容區域超出來的部分隱藏,使內容區域完全包含在該包含塊中。
然而"overflow:hidden"還有另外一個特殊的用途,那就是清除包含塊內子元素的浮動。我們先來看一個實例:
//html
<body>
<div class="parent">
<div class="child1"></div>
<div class="child2"></div>
</div>
</body>
// css
.parent{
width:300px;
background:#ddd;
border:1px solid;
}
.child1{
width:100px;
height:100px;
background:pink;
float:left;
}
.child2{
width:200px;
height:50px;
background:red;
}
結果:
上面的例子中,我們沒有設置.parent的高度,所以.parent的高度默認為auto。由于.child1設置了浮動,脫離了文檔流,所以.parent中只有.child2這一個文檔流元素。現在我們給.parent添加"overflow:hidden"
:
.parent{
overflow: hidden;
}
結果:
我們看到,給父元素添加一句"overflow:hidden",就能讓父元素包住這個脫離了文檔流的浮動元素,換句話說,"overflow:hidden"可以清除包含塊內子元素的浮動的影響。
現在我們看到了現象,可是原因是什么呢?
在解釋這個問題之前,我們先了解一下BFC的概念。
BFC
BFC(Block Formatting Context),塊級格式化上下文,它規定了內部的塊級元素的布局方式,默認情況下只有根元素(即body)一個塊級上下文。
1、BFC布局規則
- 內部的塊級元素會在垂直方向,一個接一個地放置;
- 塊級元素垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰的塊級元素會發生margin合并,不屬于同一個BFC的兩個相鄰的塊級元素不會發生margin合并;
- 每個元素的margin box的左邊,與包含border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此;
- BFC的區域不會與float box重疊;
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素;外面的元素也不會影響到容器里面的子元素;
- 計算BFC的高度時,浮動元素也參與計算。
2、創建一個BFC
首先我們要知道怎樣創建BFC。一個BFC可以被顯式觸發,只需滿足以下條件之一:
- float的值不為none;
- overflow的值不為visible;
- position的值為fixed / absolute;
- display的值為table-cell / table-caption / inline-block / flex / inline-flex。
3、BFC的應用
1)、消除margin合并
在margin合并這篇博客中,我描述了相鄰兄弟元素、父元素與第一個和最后一個子元素、空塊元素的margin合并情況。那么對于發生margin合并的元素,我們怎樣消除margin合并?
對于父子元素,我們可以通過設置padding、border、inline content、height、min-height、max-height等屬性來消除;但是相鄰的兄弟元素之間必出現margin合并,這時如果想要消除margin合并,又該怎么辦?
我們首先要搞清楚為什么會發生margin合并。這些元素(包括兄弟、父子元素等)之間之所以會發生margin合并,是因為它們屬于同一個BFC。所以,我們就知道怎么辦了,只要讓它們不屬于同一個BFC不就可以了?
我們來看在margin合并這篇博客中舉過的一個例子:
// html
<body>
<div class='bro1'></div>
<div class='bro2'> </div>
</body>
// css
body{
margin:0;
padding:0;
}
.bro1{
width:300px;
height:200px;
background:#ddd;
margin-bottom:30px;
}
.bro2{
width:200px;
height:100px;
background:pink;
margin-top:20px;
}
結果:
現在我們給.bro1新建一個BFC,并添加 overflow:hidden;
,修改代碼如下:
// html
<body>
<div class='special'>
<div class='bro1'></div>
</div>
<div class='bro2'> </div>
</body>
// css
.special{
overflow:hidden;
}
結果:
你看!margin合并消除了!
2)、包含浮動子元素
這也是我們今天的主要議題——為什么"overflow:hidden"能清除浮動的影響。
我們經常會在父元素里設置某個子元素浮動。浮動后,子元素脫離了文檔流,使得父元素無法包住這個浮動的子元素。我們通常在父元素上設置一個clearfix
的偽元素來清除浮動;同樣,我們可以利用BFC可以包含浮動這一特性來清除浮動,例子已經在本文開頭講過。
我們對本文開頭的例子作一個分析:當給.parent設置"overflow:hidden"時,實際上創建了一個超級屬性BFC,此超級屬性反過來決定了"height:auto"是如何計算的。在“BFC布局規則”中提到:計算BFC的高度時,浮動元素也參與計算。因此,父元素在計算其高度時,加入了浮動元素的高度,“順便”達成了清除浮動的目標,所以父元素就包裹住了子元素。
除了給.parent設置"overflow:hidden",我們還可以設置"display:inline-block"、"position:absolute"、"float:left"等方式來創建一個BFC,從而達到包裹浮動子元素的效果(具體使用哪種方法要看項目需求):
// css
.parent{
/* 具體使用哪個要看界面設計的情況 */
/* overflow: hidden; */
/* display:inline-block; */
/* position:absolute; */
float:left;
}
結果:
好了,關于這個問題就總結到這里。CSS的很多屬性看似簡單,深究起來才發現自己了解的僅僅只是冰山一角,前端之路,道阻且長啊!
由于個人水平有限,博客錯誤之處,煩請指正!
參考資料:
1、理解CSS中BFC
2、BFC神奇背后的原理
3、知乎:CSS中為什么overflow:hidden能清除浮動(float)的影響?原理是什么?