BFC 的全稱是 Block Formating Context,譯為“塊級格式化上下文”,是 CSS 規范中的一個概念,規定了一套渲染規則,規定了內部的子元素如何布局,以及他們和其他元素的關系等。
除了 BFC 之外,規范中還有 IFC 的概念,也就是 Inline Formating Context,譯為“內聯格式化上下文”。
BFC 和 IFC 都是 CSS 2.1 中的規范,在 CSS3 中,還有 GFC、FFC 等。
本文的重點是對 BFC 的理解,理解了 BFC 之后,就對 CSS 中的很多東西有了原理化的認知,更加明白 CSS 中的一些難點特性,如浮動、定位等。
你要知道的
在學習 BFC 之前,你需要知道下面幾個要點:
- BFC 規定了瀏覽器對于元素和子元素渲染方式
- BFC 是需要觸發條件的
- 只有觸發了 BFC 的元素才能應用 BFC 的規則
- BFC 元素和
display:block
的元素沒有半毛錢關系
BFC 的一些特性
BFC 包含以下一些常用特性:
- BFC 容器會阻止外邊距疊加
- BFC 容器會阻止其被浮動元素覆蓋
- 計算 BFC 容器的高度時,會包含浮動元素
這三個特性可以算是 BFC 中最常用的幾個特性了,可以幫助我們理解浮動、清浮動等知識。
觸發 BFC
滿足下列任意條件,就可以觸發 BFC:
-
float
設置為none
以外的值(left
,right
) -
overflow
設置為visible
以外的值(hidden
,auto
,scroll
) -
position
設置為relative
以外的值(absolute
,fixed
) -
display
設置為inline-block
,table
,table-cell
或table-caption
需要注意的是,display:table 本身并不會創建BFC,但是它會產生匿名框(anonymous boxes),而匿名框中的display:table-cell可以創建新的BFC,換句話說,觸發塊級格式化上下文的是匿名框,而不是display:table。所以通過display:table和display:table-cell創建的BFC效果是不一樣的。
上面的文字引用于那些年我們一起清除過的浮動。
應用
了解了 BFC 的常用特性以及觸發條件后,我們可以使用 HTML+CSS 來對這些理論進行驗證。下面依次驗證這幾個特性:
BFC 容器會阻止外邊距疊加
外邊距疊加是在元素在垂直方向上margin
值的疊加效應,我在這篇文章中也做了一些總結,您可以進行查看。
1.設置元素的 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.設置元素的
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.設置元素的 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;
}
效果預覽:
4.設置元素的
position
屬性使用絕對定位固定定位的元素脫離了標準文檔流,并且有了層級的概念,因此其邊距不會和其他元素的邊距產生疊加效應(因為不在同一個層級),這個效果不好演示,這里就略過了~
BFC 容器會阻止其被浮動元素覆蓋
我們知道浮動元素是一個 BFC 容器,其脫離了標準的文檔流,其后面元素就好像這個元素不存在一樣。浮動元素會一直想或者向右移動,直到其碰到了父級元素或者其他元素的邊緣才停止。
先看一個簡單的 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
}
展示效果:
可見,由于第一個段落采用了浮動,便脫離了標準文檔流,其后面的元素就好像這個浮動元素不存在一樣,直接挨著父級元素排列,所以視覺效果上,后面的那一個段落被覆蓋掉了。
由于BFC 容器會阻止其被浮動元素覆蓋,因此我們只需要讓后面的段落觸發 BFC 就可以阻止浮動元素的覆蓋啦。
1.設置元素的
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;
}
運行效果:
2.設置元素的
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;
}
運行效果:
3.設置元素的
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;
}
運行效果:
4.設置元素的
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;
}
運行效果:
這個最霸道,不僅阻止了浮動元素對其自身進行覆蓋,反而還把浮動元素給覆蓋了,666
計算 BFC 容器的高度時,會包含浮動元素
這也就是清除浮動的原理了,因為浮動會將元素的 inline-box 設置為0,而我們知道 containing-box 的高度本質上是由 inline-box 決定的(您可以參考這篇文章,里面進行了一些總結),所以如果一個元素中的元素都進行了浮動,那么這個完成元素的高度就塌陷了。為了解決這個問題,我們只需要“找回”外層元素的高度就可以了,運用到的就是 BFC 的這個特性:計算 BFC 容器的高度時,會包含浮動元素。
關于浮動這一塊,里面又有很多概念,需要再用一片文章來寫,這里就不再往下寫了。后面會出一篇和浮動有關的文章,再進行說明。
總結
本文主要講解了 BFC 的概念,BFC 是 CSS 2.1 中的一項規范,規定了其和子元素的一些呈現方式。BFC 需要一些觸發條件,和浮動、定位、行內塊等知識點關系緊密,需要我們去深入理解。
附:參考資料
那些年我們一起清除過的浮動
理解 BFC (Block Formatting Model)
CSS之BFC詳解
深度理解現代瀏覽器中的BFC和IE下的haslayout
完。