走在前端的大道上
本篇將自己讀過的相關 盒模型BFC 文章中,對自己有啓發的章節片段總結在這(會對原文進行刪改),會不斷豐富提煉總結更新。
一.常見定位方案
在講 BFC 之前,我們先來了解一下常見的定位方案,定位方案是控制元素的佈局,有三種常見方案:
- 普通流 (normal flow)
在普通流中,元素按照其在 HTML 中的先後位置至上而下佈局,在這個過程中,行內元素水平排列,直到當行被佔滿然後換行,塊級元素則會被渲染爲完整的一個新行,除非另外指定,否則所有元素默認都是普通流定位,也可以說,普通流中元素的位置由該元素在 HTML 文檔中的位置決定。
- 浮動 (float)
在浮動佈局中,元素首先按照普通流的位置出現,然後根據浮動的方向儘可能的向左邊或右邊偏移,其效果與印刷排版中的文本環繞相似。
- 絕對定位 (absolute positioning)
在絕對定位佈局中,元素會整體脫離普通流,因此絕對定位元素不會對其兄弟元素造成影響,而元素具體的位置由絕對定位的座標決定。
二、BFC 概念
Formatting context(格式化上下文) 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用。常見的FC有BFC、IFC,還有GFC和FFC。
那麼 BFC 是什麼呢?
BFC 即 Block Formatting Contexts (塊級格式化上下文),它屬於上述定位方案的普通流。
一個BFC的範圍 包含創建該上下文元素的所有子元素,但不包括創建了新BFC的子元素的內部元素。這從另一方角度說明,一個元素不能同時存在於兩個BFC中。因爲如果一個元素能夠同時處於兩個BFC中,那麼就意味着這個元素能與兩個BFC中的元素髮生作用,就違反了BFC的隔離作用。
具有 BFC 特性的元素可以看作是隔離了的獨立容器,容器裏面的元素不會在佈局上影響到外面的元素,並且 BFC 具有普通容器所沒有的一些特性。
通俗一點來講,可以把 BFC 理解爲一個封閉的大箱子,箱子內部的元素無論如何翻江倒海,都不會影響到外部。
三、佈局規則
- 內部的Box會在垂直方向上一個接一個的放置
- 每個元素的左外邊距與包含塊的左邊界相接觸(從左向右),即使浮動元素也是如此。(這說明BFC中子元素不會超出他的包含塊,而position爲absolute的元素可以超出他的包含塊邊界)
- 屬於同一個BFC的 兩個相鄰Box的 上下margin會發生摺疊;
- BFC的區域不會與float的元素區域重疊(阻止元素被浮動元素覆蓋)
- 計算BFC的高度時,浮動子元素也參與計算(清除內部浮動)
四、觸發 BFC
只要元素滿足下面任一條件即可觸發 BFC 特性:
- body 根元素
- 浮動元素:float 除 none 以外的值,如left、right
- 絕對定位元素:position (absolute、fixed)
- display 爲 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 ,如hidden、auto、scroll
注意:有些文章中說HTML可以觸發BFC,沒有說body,按照上邊介紹的一個BFC的範圍
和下邊的案例1
來看,HTML能不能觸發不確定,但是body是可以的
五、BFC的特性及應用
1.普通流中兩個相鄰的塊元素 垂直方向上的 margin會摺疊
<style>
.p {
width:200px;
height:50px;
margin:50px 0;
background-color:red;
}
</style>
<body>
<div class="p"></div>
<div class="p"></div>
</body>
效果圖是:
發生外邊距摺疊,是因爲他們 同屬於 body這個根元素
讓 它們 不屬於同一個BFC,就能避免外邊距摺疊:
<style>
.wrap {
overflow:hidden;
}
.p {
width:200px;
height:50px;
margin:50px 0;
background-color:red;
}
</style>
<body>
<div class="p"></div>
<div class="wrap">
<div class="p"></div>
</div>
</body>
效果圖是:
2.普通流中 父子嵌套關係的2個塊元素 垂直方向上的 margin會摺疊
<style>
.father {
width: 200px;
height: 200px;
background: skyblue;
}
.son {
width: 100px;
height: 100px;
background: red;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
然後,我們給子元素添加一個margin-top: 50px時
.son {
width: 100px;
height: 100px;
background: red;
margin-top: 50px;
}
我們神奇的發現父子元素同時"掉下來了50px",如圖所示
3.BFC可以包含浮動的元素(清除浮動)
正常情況下,浮動的元素會脫離普通文檔流,所以下面的代碼裏:
<style>
.wrap {
border: 1px solid #000;
}
.inner {
float: left;
width: 50px;
height: 50px;
background: #eee;
}
</style>
<body>
<div class="wrap">
<div class="inner"></div>
</div>
</body>
外層的div會無法包含 內部浮動的div,效果見下圖:
但如果我們 觸發外部容器的BFC,根據BFC規範 計算BFC的高度時,浮動元素也參與計算,那麼外部div容器就可以包裹着浮動元素,所以只要把代碼修改如下:
<style>
.wrap {
border: 1px solid #000;
overflow:hidden;
}
.inner {
float: left;
width: 50px;
height: 50px;
background: #eee;
}
</style>
<body>
<div class="wrap">
<div class="inner"></div>
</div>
</body>
就可以完成以下效果:
4.實現2欄自適應佈局
要求左側固定300px,右側自適應的佈局
<style>
.wrapper, * {
padding: 0;
margin: 0;
}
.left {
width: 300px;
height: 100px;
background: red;
float: left;
}
.right {
height: 100px;
background: skyblue;
overflow: hidden;
}
</style>
<div class="wrapper">
<div class="left">left</div>
<div class="right">right</div>
</div>
原理:BFC元素不會和浮動的元素重疊
參考文章:
10 分鐘理解 BFC 原理
CSS中重要的BFC
淺析CSS裏的 BFC 和 IFC
前端人人都應該理解的盒模型BFC渲染機制