什麼是 BFC
BFC 全稱是 Block Formatting Context,即塊格式化上下文。
除了 BFC,還有:
- IFC(行級格式化上下文)- inline 內聯
- GFC(網格佈局格式化上下文)-
display: grid - FFC(自適應格式化上下文)-
display: flex或display: inline-flex
注意:同一個元素不能同時存在於兩個 BFC 中
它是 Web 頁面的可視 CSS 渲染的一部分,是塊盒子的佈局過程發生的區域,也是浮動元素與其他元素交互的區域。怎麼理解呢?實際就是説 BFC 是一個渲染區域,並且有自己的一套渲染規則,使其內部佈局的元素具有一些特性。
BFC 提供一個獨立的佈局環境,BFC 內部的元素佈局與外部互不影響。
塊級元素
CSS 屬性值 display 為 block,list-item,table 的元素。
塊級盒具有以下特性:
- CSS 屬性值 display 為 block,list-item,table 時,它就是塊級元素
- 佈局上,塊級盒呈現為豎直排列的塊
- 每個塊級盒都會參與 BFC 的創建
- 每個塊級元素都會至少生成一個塊級盒,稱為主塊級盒;一些元素可能會生成額外的塊級盒,比如
<li>,用來存放項目符號
創建 BFC
以下元素會創建 BFC
- 根元素(
<html>) - 浮動元素(
float不為none) - 絕對定位元素(
position為absolute或fixed) - 表格的標題和單元格(
display為table-caption,table-cell) - 匿名錶格單元格元素(
display為table或inline-table) - 行內塊元素(
display為inline-block) overflow的值不為visible的元素- 彈性元素(
display為flex或inline-flex的元素的直接子元素) - 網格元素(
display為grid或inline-grid的元素的直接子元素)
以上是 CSS2.1 規範定義的 BFC 觸發方式,在最新的 CSS3 規範中,彈性元素和網格元素會創建 F(Flex)FC 和 G(Grid)FC。
BFC 的特性
- BFC 是頁面上的一個獨立容器,容器裏面的子元素不會影響外面的元素。
- BFC 內部的塊級盒會在垂直方向上一個接一個排列
- 同一 BFC 下的相鄰塊級元素可能發生外邊距摺疊,創建新的 BFC 可以避免外邊距摺疊
- 每個元素的外邊距盒(margin box)的左邊與包含塊邊框盒(border box)的左邊相接觸(從右向左的格式的話,則相反),即使存在浮動
- 浮動盒的區域不會和 BFC 重疊
- 計算 BFC 的高度時,浮動元素也會參與計算
如果不太理解的,在下面 BFC 的應用我會提及。
BFC 的應用
自適應兩列布局
左列浮動(定寬或不定寬都可以),給右列開啓 BFC。
/* html 代碼 */
<div>
<div class="left">浮動元素,無固定寬度</div>
<div class="right">自適應</div>
</div>
/* css 代碼 */
* {
margin: 0;
padding: 0;
}
.left {
float: left;
height: 200px;
margin-right: 10px;
background-color: red;
}
.right {
overflow: hidden;
height: 200px;
background-color: yellow;
}
- 將左列設為左浮動,將自身高度塌陷,使得其它塊級元素可以和它佔據同一行的位置。
- 右列為 div 塊級元素,利用其自身的流特性佔滿整行。
- 右列設置
overflow: hidden,觸發 BFC 特性,使其自身與左列的浮動元素隔離開,不佔滿整行。
這即是上面説的 BFC 的特性之一:浮動盒的區域不會和 BFC 重疊
防止外邊距(margin)重疊
兄弟元素之間的外邊距重疊
/* html 代碼 */
<div>
<div class="child1"></div>
<div class="child2"></div>
</div>
/* css 代碼 */
* {
margin: 0;
padding: 0;
}
.child1 {
width: 100px;
height: 100px;
margin-bottom: 10px;
background-color: red;
}
.child2 {
width: 100px;
height: 100px;
margin-top: 20px;
background-color: green;
}
兩個塊級元素,紅色 div 距離底部 10px,綠色 div 距離頂部 20px,按道理應該兩個塊級元素相距 30px 才對,但實際卻是取距離較大的一個,即 20px。
塊級元素的上外邊距和下外邊距有時會合並(或摺疊)為一個外邊距,其大小取其中的較大者,這種行為稱為外邊距摺疊(重疊),注意這個是發生在屬於同一 BFC 下的塊級元素之間
根據 BFC 特性,創建一個新的 BFC 就不會發生 margin 摺疊了。比如我們在他們兩個 div 外層再包裹一層容器,加屬性overflow: hidden,觸發 BFC,那麼兩個 div 就不屬於同個 BFC 了。
/* html 代碼 */
<div>
<div class="parent">
<div class="child1"></div>
</div>
<div class="parent">
<div class="child2"></div>
</div>
</div>
/* css 代碼 */
.parent {
overflow: hidden;
}
/* ... */
這個關於兄弟元素外邊距疊加的問題,除了觸發 BFC 也有其他方案,比如你統一隻用上邊距或下邊距,就不會有上面的問題。
父子元素的外邊距重疊
這種情況存在父元素與其第一個或最後一個子元素之間(嵌套元素)。
如果在父元素與其第一個/最後一個子元素之間不存在邊框、內邊距、行內內容,也沒有創建塊格式化上下文、或者清除浮動將兩者的外邊距 分開,此時子元素的外邊距會“溢出”到父元素的外面。
如下代碼:
/* HTML 代碼 */
<div id="parent">
<div id="child"></div>
</div>
/* CSS 代碼 */
* {
margin: 0;
padding: 0;
}
#parent {
width: 200px;
height: 200px;
background-color: green;
margin-top: 20px;
}
#child {
width: 100px;
height: 100px;
background-color: red;
margin-top: 30px;
}
如上圖,紅色的 div 在綠色的 div 內部,且設置了margin-top為 30px,但我們發現紅色 div 的頂部與綠色 div 頂部重合,並沒有距離頂部 30px,而是溢出到父元素的外面計算。即本來父元素距離頂部只有 20px,被子元素溢出影響,外邊距重疊,取較大的值,則距離頂部 30px。
解決辦法:
- 給父元素觸發 BFC(如添加
overflow: hidden) - 給父元素添加 border
- 給父元素添加 padding
這樣就能實現我們期望的效果了:
清除浮動解決令父元素高度坍塌的問題
當容器內子元素設置浮動時,脱離了文檔流,容器中總父元素高度只有邊框部分高度
/* html 代碼 */
<div class="parent">
<div class="child"></div>
</div>
/* css 代碼 */
* {
margin: 0;
padding: 0;
}
.parent {
border: 4px solid red;
}
.child {
float: left;
width: 200px;
height: 200px;
background-color: blue;
}
解決辦法:給父元素觸發 BFC,使其有 BFC 特性:計算 BFC 的高度時,浮動元素也會參與計算
.parent {
overflow: hidden;
border: 4px solid red;
}
上面我們都是用的overflow: hidden觸發 BFC,因為確實常用嘛,但是觸發 BFC 也不止是隻有這一種方法,如上面寫的所示。
比如可以設置float: left; float: right; display: inline-block; overflow: auto; display: flex; display:" table; position為absolute或fixed等等,這些都可以觸發,不過父元素寬度表現不一定相同,但父元素高度都被撐出來了。當然實際運用可不是隨便挑一個走,還是根據場景選擇。
- ps: 個人技術博文 Github 倉庫,覺得不錯的話歡迎 star,鼓勵我繼續寫作吧~