學習HTML的時候遇到過這種情況:
兩個塊級box垂直方向相鄰,如果設置它們的上下margin,就會發生重疊(margin塌陷)現象。
當時也沒有想太多,只知道有這種情況,在使用的時候會盡量設置單個margin或者設置padding值,來避免出現重疊現象,但閑下來時,我仔細想了下這個問題,然后查詢了一些資料,結果引出來一個東西 BFC。
BFC
什么是BFC?
要了解什么是BFC,就要涉及一些CSS布局的一些基本概念,其中塊級盒的概念要清楚。
盒模型
在W3C規定里,完整的盒模型為:
- content:內容(主體)
- padding:內邊距
- border:邊框
- margin:外邊距
每個塊級元素都會自動生成一個塊級盒block-level box,每個塊級盒的盒模型結構都如上圖盒模型一樣。
其中,margin、padding、border、content分別定義了元素的四種邊,每種類型的邊定義了一種盒子,分別是margin box、padding box、border box 、content box。而控制塊級盒之間的垂直間距的就是margin box。
我們對塊級元素布局的描述為:
普通流中的塊元素獨占一行,然后從上往下一個接一個的排布,相鄰元素間會有外邊距折疊
為什么會是這種布局呢?原因就是BFC的存在
BFC定義
BFC(Block formatting context)直譯為"塊級格式化上下文"。它是一個獨立的渲染區域,只有Block-level box參與, 它規定了內部的Block-level Box如何布局,并且與這個區域外部毫不相干。
BFC布局規則(重點)
- 內部的Box會在垂直方向,一個接一個地放置。
- Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發生重疊
- 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此。
- BFC的區域不會與float box重疊。
- BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
- 計算BFC的高度時,浮動元素也參與計算
觸發(創建)BFC
- float的值不為none
- overflow的值為auto、scroll或hidden。
- display的值為inline-block, table-cell, table-caption, flex, inline-flex中的任何一個。
- position的值不為relative和static(可以為absolute或fixed)
BFC功能和作用
1. 自適應左右兩欄布局
代碼:
<style>
html,body{
width: 100%;
height: 100%;
}
.box1{
width: 180px;
height: 300px;
background-color: purple;
float: left;
}
.box2{
height: 100%;
background-color: yellow;
}
</style>
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
顯示效果:
根據BFC布局規則:
每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對于從左往右的格式化,否則相反)。即使存在浮動也是如此。
因此,即時存在浮動元素box1,但box2的左邊依然緊貼父元素左邊界。
如何實現左右兩欄分布?
根據BFC布局規則:
BFC的區域不會與float box重疊
可以設置box2為BFC,觸發BFC效果,實現自適應兩欄布局。
.box2{
height: 100%;
background-color: yellow;
overflow: hidden;
}
當觸發box2生成BFC后,這個新的BFC就不會與浮動的box1重疊。因此box2會根據包含塊(父元素)的寬度,和box1的寬度,自動變窄(自適應)。效果如下:
清除內部浮動
代碼:
<style>
html,body{
width: 100%;
height: 100%;
}
.father{
width: 200px;
border:8px solid #d02c38;
}
.son{
width: 80px;
height: 80px;
border:5px solid #666666;
display: inline-block;
float: left;
}
</style>
<body>
<div class="father">
<div class="son"></div>
<div class="son"></div>
</div>
</body>
頁面顯示為:
father盒子中的son盒子全部為浮動后,內容無法撐起父盒子的高度,所以father盒子顯示為一條寬度為16px的實線,想撐起父盒子的高度,就需要清除浮動帶來的影響。
根據BFC規則:
計算BFC的高度時,浮動元素也參與計算
因此,father元素觸發BFC,那么father元素計算高度的時候,會把son元素的高度也計算進去,相當于給father設置了高度,達到清除浮動的效果。
防止垂直重疊
在文章開頭就說到,相鄰兩個塊級元素的上下margin值會發生重疊現象。現在可以通過BFC來解決這個問題。
代碼:
<style>
html,body{
width: 100%;
height: 100%;
}
.box1{
width: 100px;
height: 100px;
background-color: red;
margin-bottom: 50px;
}
.box2{
width: 100px;
height: 100px;
background-color: blue;
margin-top: 50px;
}
</style>
<body>
<div class="box1">box1</div>
<div class="box2">box2</div>
</body>
效果顯示:兩個盒子之間的距離設置上下各50px,按我們理解的來算應該是100px,但實際上是50px,外邊距發生了重疊。
根據BFC規則:
Box垂直方向的距離由margin決定。屬于同一個BFC的兩個相鄰Box的margin會發生重疊
我們可以把這兩個盒子設為不同的BFC,就能避免重疊。實際是給下面的盒子box2設置屬性:
.box2{
width: 100px;
height: 100px;
background-color: blue;
margin-top: 50px;
display: inline-block;
/*overflow: hidden;*//在此處無效
}
效果為:
BFC的這些作用,都體現了BFC的最大的規則屬性:
BFC就是頁面上的一個隔離的獨立容器,容器里面的子元素不會影響到外面的元素。反之也如此。
因為BFC內部的元素和外部的元素絕對不會互相影響,因此, 當BFC外部存在浮動時,它不應該影響BFC內部Box的布局,BFC會通過變窄,而不與浮動有重疊。同樣的,當BFC內部有浮動時,為了不影響外部元素的布局,BFC計算高度時會包括浮動的高度。避免margin重疊,也是這樣的一個道理。