本文我們主要和大家分享關於CSS中重要的BFC詳解,CSS中有個重要的概念BFC,搞懂BFC可以讓我們理解CSS中某些原本詭異(??)的地方。
1. 簡介
在解釋BFC之前,先說一下文檔流。我們常說的文檔流其實分為定位流、浮動流、普通流三種。而普通流其實就是指BFC中的FC。FC(Formatting Context),直譯過來是格式化上下文,它是頁面中的一塊渲染地區,有一套渲染規則,決定了其子項目如何布局,以及和其他元素之間的關係和作用。常見的FC有BFC、IFC,還有GFC和FFC。
BFC(Block Formatting Context)塊級格式化上下文,是用於布局塊級盒子的一塊渲染地區,或者說是在一定條件下的一種渲染規則。
MDN上的解釋:BFC是Web頁面的可視化CSS渲染的部分,是塊級盒布局發生的地區,也是浮動元素與其他元素互動的地區。
2. BFC觸發方式
根項目,即HTML標籤
float的值不為 none,為 left
、right
overflow值不為 visible,為 auto
、scroll
、hidden
display值為 inline-block
、table-cell
、table-caption
、flex
、inline-flex
、grid
、inline-grid
position值為 absolute
、fixed
注意:display:table也可以產生BFC的原因在於Table會預設產生一個匿名的table-cell,是這個匿名的table-ccell產生了BFC。
3. 約束規則
瀏覽器對BFC地區的約束規則:
產生BFC元素的子項目會一個接一個的放置。垂直方向上他們的起點是一個包含塊的頂部,兩個相鄰子項目之間的垂直距離取決於元素的margin特性。在BFC中相鄰的區塊層級元素的外邊距會摺疊(Mastering margin collapsing)。
產生BFC元素的子項目中,每一個子項目左外邊距與包含塊的左邊界相接觸(對於從右至左的格式化,右外邊距接觸右邊界),即使浮動元素也是如此(儘管子項目的內容地區會由於浮動而壓縮),除非這個子項目也建立了一個新的BFC(如它自身也是一個浮動元素)。
規則解讀:
內部的Box會在垂直方向上一個接一個的放置
內部的Box垂直方向上的距離由margin決定。(完整的說法是:屬於同一個BFC的兩個相鄰Box的margin會發生摺疊,不同BFC不會發生摺疊。)
每個元素的左外邊距與包含塊的左邊界相接觸(從左向右),即使浮動元素也是如此。(這說明BFC中子項目不會超出他的包含塊,而position為absolute的元素可以超出他的包含塊邊界)
BFC的地區不會與float的元素地區重疊
計算BFC的高度時,浮動子項目也參與計算
4. 作用
BFC是頁面上的一個隔離的獨立容器,容器裡面的子項目不會影響到外面元素,反之亦然。我們可以利用BFC的這個特性來做很多事。
4.1 阻止元素被浮動元素覆蓋
一個正常文檔流的block元素可能被一個float元素覆蓋,擠占正常文檔流,因此可以設定一個元素的float、display、position值等方式觸發BFC,以阻止被浮動盒子覆蓋。
查看DEMO
4.2 可以包含浮動元素
通過改變包含浮動子項目的父盒子的屬性值,觸發BFC,以此來包含子項目的浮動盒子。
查看DEMO
4.3 阻止相鄰元素的margin合并
屬於同一個BFC的兩個相鄰塊級子項目的上下margin會發生重疊,(設定writing-mode:tb-rl時,水平margin會發生重疊)。所以當兩個相鄰塊級子項目分屬於不同的BFC時可以阻止margin重疊。
這裡給任一個相鄰塊級盒子的外麵包一個p,通過改變此p的屬性使兩個原盒子分屬於兩個不同的BFC,以此來阻止margin重疊。
查看DEMO
但是這裡有個疑問:
如果外麵包一層p,設定能觸發BFC的任何屬性都能阻止相鄰元素的margin合并。因為分屬不同BFC不會發生margin合并。
而如果在外面不包一個p的話,當設定display為inline-block、inline-flex、table-captain,和position為absolute、fixed,float為left、right是可以阻止margin合并的。這裡問題來了:
我們知道設定position和float會讓元素脫離文檔流並且又建立新的BFC,所以兩個元素就不是相鄰元素了,因此可以阻止相鄰元素margin合并,但是inline-block、inline-flex、inline-grid、table-captain為什麼可以呢?如果有人知道為什麼,請告知~