BFC,你也許聽過這個詞,但是你可能不是很有底氣地解釋清楚。寫樣式的時候,往往加了一個樣式或者改了一個屬性,就能達到你期望的效果,一切都是如此地神奇。BFC就是神奇之一,它也是最熟悉的陌生人,因為你一不小心就會觸發它然而你并沒有意識到它正在神奇地發揮作用。
初探BFC
我們先看看CSS布局的基本單位:
- block-level box: display 屬性為 block, list-item, table 的元素,會生成 block-level box,并且參與 block formatting context
- inline-level box: display 屬性為 inline, inline-block, inline-table 的元素,會生成 inline-level box,并且參與 inline formatting context
那這個formatting context又是什么玩意兒?
它是W3C CSS2.1規范中的一個概念。它是頁面中的一塊渲染區域,并且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。也就是說我們平時在布局的時候,它默默地提供了一個環境,使得HTML元素在這個環境中按照一定規則進行布局。
最常見的formatting context有Block Formatting Context(BFC)和Inline Formatting Context(IFC),CSS3中還增加了GridLayout Formatting Context(GFC)和Flex Formatting Context(FFC),這里就不深入研究了。
BFC定義:它是一個獨立的渲染區域,只有block-level box參與,其中的元素按照規定的渲染規則進行布局,并且這個區域與外部毫不相干。
BFC的布局規則與觸發規則
剛才我們說到BFC中的元素有一套規定的布局規則:
- 內部的元素會在垂直方向一個接一個地放置
- 元素垂直方向的距離由margin決定,屬于同一個BFC的兩個相鄰元素的margin會發生重疊
- 每個元素的左外邊距與包含塊的左邊界相接觸(對于從左往右,否則相反),即使存在浮動也是如此
- BFC的區域不會與float元素重疊
- 計算BFC的高度時,浮動元素也參與計算
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素,反之也如此
剛才我們又提到BFC是一塊渲染區域,那這塊渲染區域到底在哪,它又是有多大,這些由生成BFC的元素來決定,CSS2.1中規定滿足下列CSS聲明的元素便會生成BFC(觸發規則):
根元素
- float的值不為none
- overflow的值不為visible
- position的值為absolute或fixed
- display的值為inline-block, table-cell, table-caption, flex, inline-flex
注:display: table也認為可以生成BFC,主要原因是table會默認生成一個匿名的table-cell,正是這個匿名的table-cell生成了BFC上面這些CSS聲明的元素生成了BFC,而它們本身并不是BFC,這一點需要區分。
BFC的應用
說了這么多有用沒用的,我們平時布局的時候到底怎么應用呢:
1.防止垂直margin重疊
有點布局經驗的朋友都知道margin collapse,也就是相鄰的垂直元素同時設置了margin后,實際margin值會塌陷到其中較大的那個值。其根本原理就是它們處于同一個BFC,符合“屬于同一個BFC的兩個相鄰元素的margin會發生重疊”的規則。
我們可以在其中一個元素外面包裹一層容器,并觸發該容器生成一個BFC。那么兩個元素便屬于不同的BFC,就不會發生margin重疊了:
<style data-filtered="filtered">
.wrap{
overflow: hidden;
}
p{
width: 200px;
line-height: 100px;
margin: 100px;
background: #000;
color: #fff;
text-align: center;
}
</style>
<p>我屬于一個BFC</p>
<div class="wrap">
<p>我屬于另一個BFC</p>
</div>
如果是我的話會直接設置200px,或者只設置其中一個元素的margin(懶可以偷,但原理需知道)
2.防止浮動子元素高度塌陷
<style data-filtered="filtered">
.parent{
width: 300px;
border: 3px solid #000;
overflow: hidden;
}
.child{
float: left;
width: 100px;
height: 100px;
border: 3px solid #f00;
color: #f00;
}
</style>
<div class="parent">
<div class="child">float: left</div>
<div class="child">float: left</div>
</div>
如果我們將.parent元素的overflow: hidden去掉,那么.parent元素就獲取不到浮動元素的高度了。但是加上overflow屬性后觸發了BFC,計算BFC的高度時,浮動元素也參與了計算。
3.防止文字(或其他元素)環繞
<style data-filtered="filtered">
.parent{
width: 300px;
border: 3px solid #000;
}
.child{
float: left;
width: 100px;
height: 100px;
border: 3px solid #f00;
color: #f00;
}
.text{
overflow: hidden;
}
</style>
<div class="parent">
<div class="child">float: left</div>
<div class="text">我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞我只是文字但我不會環繞</div>
</div>
正常情況下,如果一個塊級元素設置成了float,那么他的兄弟元素會環繞其布局。這里我們給.text加上overflow,文字所在的區域就產生了BFC,元素的左邊總是觸碰到容器的左邊,即使存在浮動也是如此。
這里舉例了幾個比較經典的應用,我們在以后的布局中也可以慢慢探索其中的奧秘之處,做一個能寫一手好樣式還能懂原理的前端er。
學習前端的同學注意了!!!
學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入前端學習交流群461593224,我們一起學前端!