一、 什么是BFC?
1 CSS布局的基本單位:Box(盒模型)
Box是CSS布局的對象和基本單位,一份網(wǎng)頁由多個Box根據(jù)其排列規(guī)則組合而成。根據(jù)CSS規(guī)范,每個HTML元素都有一個默認的display屬性值,用于確定元素的類型,進而決定這個Box的類型。
div、h1~6、等默認display屬性值為:block;
span、a等默認display屬性值為:inline
img、等默認display屬性值為:inline-block
Box類型:
-
Block-level box:display屬性值為block、list-item、table的元素,會生成Block-level box; -
Inline-level box:display屬性值為inline、inline-block、inline-table的元素,會生成Inline-level box;
2 Formatting Context
Formatting Context是頁面中的一塊渲染區(qū)域,并且有一套渲染規(guī)則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。
Formatting Context決定了Box內(nèi)子元素如何定位,以及Box與其他元素的關系及相互作用
Box類型不同,其Formatting Context(決定如何渲染文檔的容器)不同,Box內(nèi)的元素以不同方式進行渲染,常見的Formatting Context:
- Block Formatting Context(BFC):只有
Block-level box參與; - Inline Formatting Context(IFC):
Inline-level box參與;
3 BFC
Block Formatting Context(“塊級排版上下文”),是一個 獨立的渲染區(qū)域,只有Block-level box參與,規(guī)定內(nèi)部的Block-level box如何布局,與這個區(qū)域外不相干
4 BFC布局規(guī)則
- 同一個BFC內(nèi)部的Box在垂直方向,一個接一個地排列;
- Box垂直方向的間距由
margin值決定,屬于同一個BFC內(nèi)的兩個相鄰Box的margin值會發(fā)生重疊,重疊的結果:間距為較寬的margin值; - BFC內(nèi)部每個Box的左邊
margin與其包含塊的左邊border相接處(對于從左往右的格式化,否則相反),即使浮動也是如此; - 包含塊內(nèi)部子元素的每個BFC不會重疊,如果設置
float屬性,會在水平依次排開 - BFC是頁面上一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素(反之,亦反);
- 計算BFC的高度時,其內(nèi)的浮動元素也參與;
二、生成BFC的元素
- 根元素;
-
float屬性值不為none; -
position屬性值為absolte或者fixed; -
display屬性值為inline-block、table-cell、table-caption、flex、inline-flex; -
overflow屬性值不為visible。
三、BFC的作用與原理
1 自適應兩欄布局
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
.aside {
width: 100px;
height: 150px;
float: left;
background: #f66;
}
.main {
height: 200px;
background: #fcc;
}
</style>
</head>
<body>
<div class="aside"></div>
<div class="main"></div>
</body>
</html>
根據(jù)第3條規(guī)則:BFC內(nèi)部每個Box的左邊
margin與其包含塊的左邊border相接處(對于從左往右的格式化,否則相反),即使浮動也是如此;
注解規(guī)則3:.aside和.main都在根元素(包含塊的BFC)下,其內(nèi)的每個Box的margin left都與根元素的border left相接觸。.aside由于float:left;向上浮動(顯示層級變高),變成了一個BFC,并且脫離包含塊中BFC的文檔流,.main會與.aside重疊
根據(jù)第4條規(guī)則:包含塊內(nèi)部子元素的每個BFC不會重疊,如果設置
float屬性,會在水平依次排開
注解規(guī)則四:因為.main沒有其display屬性默認值為block,沒有生成包裹它的子BFC,所以會與.aside重疊,如果將.main生成一個包含的BFC,.main和.aside會分開。
將.main設置生成BFC的方法:
-
.main設置為overflow:hidden;:溢出隱藏,.main生成BFC后,其寬度繼承自body為300px,平鋪開后,加上.aside寬度應該為400px,超過了包含塊的寬度,溢出隱藏指隱藏右側超出的100px;


-
.main設置為float:left;如果不指定.main的寬度,則.main不會顯示。元素設置浮動后,如果不顯式指定寬度,其寬度有內(nèi)容撐開,沒有內(nèi)容時則不顯示。
2 清除內(nèi)部浮動
<!DOCTYPE html>
<html>
<head>
<title></title>
<style>
.par {
border: 5px solid #fcc;
width: 300px;
}
.child {
border: 5px solid #f66;
width:100px;
height: 100px;
float: left;
}
</style>
</head>
<body>
<div class="par">
<div class="child"></div>
<div class="child"></div>
</div>
</body>
</html>

根據(jù)第6規(guī)則:計算BFC的高度時,其內(nèi)的浮動元素也參與;
注解規(guī)則6:由于兩個.child元素設置了float(生成兩個子BFC),脫離文檔流,并且其包含塊不是沒有BFC,所以高度沒有被撐開,只顯示了包含塊的上下邊框。
將包含塊生成BFC即可撐開高度,利用浮動元素也參與BFC高度的計算。
/*利用overflow:hidden將par生成BFC*/
.par {
overflow: hidden;
}

3 防止margin垂直重疊
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
</head>
<body>
<p>Haha</p>
<p>Hehe</p>
</body>
</html>

根據(jù)第2條規(guī)則:Box垂直方向的間距由
margin值決定,屬于同一個BFC內(nèi)的兩個相鄰Box的margin值會發(fā)生重疊,重疊的結果:間距為較寬的margin值;
注解規(guī)則2:由于兩個p元素沒有生成BFC,并且都在根元素內(nèi),根據(jù)BFC第6條規(guī)則,margin值會發(fā)生重疊。只需要在一個p元素外包裹一層容器,并將該容器生產(chǎn)一個BFC,便不會再重疊。
<!DOCTYPE html>
<html lang="en">
<head>
<title>Document</title>
<style>
.wrap {
overflow: hidden;
}
p {
color: #f55;
background: #fcc;
width: 200px;
line-height: 100px;
text-align:center;
margin: 100px;
}
</style>
</head>
<body>
<p>Haha</p>
<div class="wrap">
<p>Hehe</p>
</div>
</body>
</html>

三、總結歸納
規(guī)格第5條:BFC是頁面上一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素(反之,亦反);
- BFC外部和內(nèi)部的元素不會相互影響 ,所以BFC外部存在浮動時,不會影響其內(nèi)部Box的布局,BFC通過溢出隱藏不與浮動有重疊;
- 當BFC內(nèi)部有浮動時,為不影響外部元素的布局,計算BFC高度時要考慮浮動元素的高度。(避免
margin的重疊道理相同:利用一個BFC將其包裹起來)
自己理解的BFC:
BFC是存在于普通文檔流中,用于記錄Box自身尺寸,不會隨浮動、定位、溢出隱藏而改變。相當于只位于普通文檔中的Box模型,其布局不會因為BFC內(nèi)部元素改變而改變。
參考博文: