BFC 的全稱是 Block Formating Context,譯為“塊級(jí)格式化上下文”,是 CSS 規(guī)范中的一個(gè)概念,規(guī)定了一套渲染規(guī)則,規(guī)定了內(nèi)部的子元素如何布局,以及他們和其他元素的關(guān)系等。
除了 BFC 之外,規(guī)范中還有 IFC 的概念,也就是 Inline Formating Context,譯為“內(nèi)聯(lián)格式化上下文”。
BFC 和 IFC 都是 CSS 2.1 中的規(guī)范,在 CSS3 中,還有 GFC、FFC 等。
本文的重點(diǎn)是對(duì) BFC 的理解,理解了 BFC 之后,就對(duì) CSS 中的很多東西有了原理化的認(rèn)知,更加明白 CSS 中的一些難點(diǎn)特性,如浮動(dòng)、定位等。
你要知道的
在學(xué)習(xí) BFC 之前,你需要知道下面幾個(gè)要點(diǎn):
- BFC 規(guī)定了瀏覽器對(duì)于元素和子元素渲染方式
- BFC 是需要觸發(fā)條件的
- 只有觸發(fā)了 BFC 的元素才能應(yīng)用 BFC 的規(guī)則
- BFC 元素和
display:block的元素沒有半毛錢關(guān)系
BFC 的一些特性
BFC 包含以下一些常用特性:
- BFC 容器會(huì)阻止外邊距疊加
- BFC 容器會(huì)阻止其被浮動(dòng)元素覆蓋
- 計(jì)算 BFC 容器的高度時(shí),會(huì)包含浮動(dòng)元素
這三個(gè)特性可以算是 BFC 中最常用的幾個(gè)特性了,可以幫助我們理解浮動(dòng)、清浮動(dòng)等知識(shí)。
觸發(fā) BFC
滿足下列任意條件,就可以觸發(fā) BFC:
-
float設(shè)置為none以外的值(left,right) -
overflow設(shè)置為visible以外的值(hidden,auto,scroll) -
position設(shè)置為relative以外的值(absolute,fixed) -
display設(shè)置為inline-block,table,table-cell或table-caption
需要注意的是,display:table 本身并不會(huì)創(chuàng)建BFC,但是它會(huì)產(chǎn)生匿名框(anonymous boxes),而匿名框中的display:table-cell可以創(chuàng)建新的BFC,換句話說,觸發(fā)塊級(jí)格式化上下文的是匿名框,而不是display:table。所以通過display:table和display:table-cell創(chuàng)建的BFC效果是不一樣的。
上面的文字引用于那些年我們一起清除過的浮動(dòng)。
應(yīng)用
了解了 BFC 的常用特性以及觸發(fā)條件后,我們可以使用 HTML+CSS 來對(duì)這些理論進(jìn)行驗(yàn)證。下面依次驗(yàn)證這幾個(gè)特性:
BFC 容器會(huì)阻止外邊距疊加
外邊距疊加是在元素在垂直方向上margin值的疊加效應(yīng),我在這篇文章中也做了一些總結(jié),您可以進(jìn)行查看。
1.設(shè)置元素的 float 屬性
HTML 代碼:
<div>
<p></p>
<p></p>
</div>
CSS 代碼:
div{
height: 20em;
border: .1em dashed #ccc;
}
p{
margin: 0;
width: 5em;
height: 5em;
background: red;
}
p:first-of-type{
margin-bottom:5em ;
}
p:last-of-type{
float: left;
background: blue;
margin-top: 5em;
}
效果如下:

2.設(shè)置元素的
overflow 屬性HTML 代碼:
<div>
<p></p>
</div>
<p></p>
CSS 代碼:
div{
overflow: hidden;
}
p{
margin: 0;
width: 5em;
height: 5em;
margin-top: 5em;
background: red;
}
div > p{
margin-bottom:5em ;
margin-top: 0;
background: blue;
}
效果展示:

3.設(shè)置元素的 display 屬性
HTML 代碼:
<div>
<p></p>
</div>
<p></p>
CSS 代碼:
div{
display: table-cell;
}
p{
margin: 0;
width: 5em;
height: 5em;
margin-top: 5em;
background: red;
}
div > p{
margin-bottom:5em ;
margin-top: 0;
background: blue;
}
效果預(yù)覽:

4.設(shè)置元素的
position 屬性使用絕對(duì)定位固定定位的元素脫離了標(biāo)準(zhǔn)文檔流,并且有了層級(jí)的概念,因此其邊距不會(huì)和其他元素的邊距產(chǎn)生疊加效應(yīng)(因?yàn)椴辉谕粋€(gè)層級(jí)),這個(gè)效果不好演示,這里就略過了~
BFC 容器會(huì)阻止其被浮動(dòng)元素覆蓋
我們知道浮動(dòng)元素是一個(gè) BFC 容器,其脫離了標(biāo)準(zhǔn)的文檔流,其后面元素就好像這個(gè)元素不存在一樣。浮動(dòng)元素會(huì)一直想或者向右移動(dòng),直到其碰到了父級(jí)元素或者其他元素的邊緣才停止。
先看一個(gè)簡(jiǎn)單的 Demo:
HTML 代碼:
<div>
<p></p>
<p></p>
</div>
CSS 代碼:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em
}
展示效果:

可見,由于第一個(gè)段落采用了浮動(dòng),便脫離了標(biāo)準(zhǔn)文檔流,其后面的元素就好像這個(gè)浮動(dòng)元素不存在一樣,直接挨著父級(jí)元素排列,所以視覺效果上,后面的那一個(gè)段落被覆蓋掉了。
由于BFC 容器會(huì)阻止其被浮動(dòng)元素覆蓋,因此我們只需要讓后面的段落觸發(fā) BFC 就可以阻止浮動(dòng)元素的覆蓋啦。
1.設(shè)置元素的
float 屬性CSS 代碼:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
float: left;
}
運(yùn)行效果:

2.設(shè)置元素的
overflow 屬性CSS 代碼:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
overflow: hidden;
}
運(yùn)行效果:

3.設(shè)置元素的
display 屬性CSS 代碼:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
display: inline-block;
}
運(yùn)行效果:

4.設(shè)置元素的
position 屬性CSS 代碼:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
position: absolute;
}
運(yùn)行效果:

這個(gè)最霸道,不僅阻止了浮動(dòng)元素對(duì)其自身進(jìn)行覆蓋,反而還把浮動(dòng)元素給覆蓋了,666
計(jì)算 BFC 容器的高度時(shí),會(huì)包含浮動(dòng)元素
這也就是清除浮動(dòng)的原理了,因?yàn)楦?dòng)會(huì)將元素的 inline-box 設(shè)置為0,而我們知道 containing-box 的高度本質(zhì)上是由 inline-box 決定的(您可以參考這篇文章,里面進(jìn)行了一些總結(jié)),所以如果一個(gè)元素中的元素都進(jìn)行了浮動(dòng),那么這個(gè)完成元素的高度就塌陷了。為了解決這個(gè)問題,我們只需要“找回”外層元素的高度就可以了,運(yùn)用到的就是 BFC 的這個(gè)特性:計(jì)算 BFC 容器的高度時(shí),會(huì)包含浮動(dòng)元素。
關(guān)于浮動(dòng)這一塊,里面又有很多概念,需要再用一片文章來寫,這里就不再往下寫了。后面會(huì)出一篇和浮動(dòng)有關(guān)的文章,再進(jìn)行說明。
總結(jié)
本文主要講解了 BFC 的概念,BFC 是 CSS 2.1 中的一項(xiàng)規(guī)范,規(guī)定了其和子元素的一些呈現(xiàn)方式。BFC 需要一些觸發(fā)條件,和浮動(dòng)、定位、行內(nèi)塊等知識(shí)點(diǎn)關(guān)系緊密,需要我們?nèi)ド钊肜斫狻?/p>
附:參考資料
那些年我們一起清除過的浮動(dòng)
理解 BFC (Block Formatting Model)
CSS之BFC詳解
深度理解現(xiàn)代瀏覽器中的BFC和IE下的haslayout
完。