理解CSS中的BFC(塊級視覺化上下文)(淺顯易懂)

YXi發表於2019-10-13

常見佈局

在講 BFC 之前,我們先來了解一下常見的佈局方案,有三種常見佈局方案:

普通佈局

在普通佈局中,元素按照其在 HTML 中的先後位置從左往右,從上往下佈局。
在這個過程中,行內元素水平排列,直到當行被佔滿然後換行。塊級元素則會被渲染為完整的一個新行,除非另外指定,否則所有元素預設都是普通流定位,也可以說,普通流中元素的位置由該元素在 HTML 文件中的位置決定。

浮動佈局

在浮動佈局中,元素首先按照普通流的位置出現,然後根據浮動的方向儘可能的向左邊或右邊偏移,其效果與印刷排版中的文字環繞相似。

絕對定位

在絕對定位佈局中,元素會整體脫離普通文件流,因此絕對定位元素不會對其兄弟元素造成影響,而元素具體的位置由絕對定位的座標決定。

什麼是BFC?

Formatting context(格式化上下文) 是 W3C CSS2.1 規範中的一個概念。它是頁面中的一塊渲染區域,並且有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關係和相互作用。

那麼什麼是BFC呢?

BFC 即 Block Formatting Contexts (塊級格式化上下文),它屬於上述定位方案的普通流。

具有 BFC 特性的元素可以看作是隔離了的獨立容器,容器裡面的元素不會在佈局上影響到外面的元素,並且 BFC 具有普通容器所沒有的一些特性。

通俗一點來講,可以把 BFC 理解為一個封閉的大箱子,箱子內部的元素無論如何翻江倒海,都不會影響到外部。

BFC的特性

怎麼觸發BFC?

只要元素滿足下面任一條件即可觸發 BFC 特性:

  • HTML 根元素

  • 浮動元素:float 除 none 以外的值

  • 絕對定位元素:position (absolute、fixed)

  • display 為 inline-block、table-cells、flex

  • overflow 除了 visible 以外的值 (hidden、auto、scroll)

BFC的約束規則

  • 內部的Box會在垂直方向上一個接一個的放置

  • 垂直方向的距離有margin決定(屬於同一個BFC的兩個相鄰Box的margin會發生重疊,與方向無關)

  • 每個元素的margin box的左邊, 與包含塊border box的左邊相接觸(對於從左往右的格式化,否則相反)。即使存在浮動也是如此

  • BFC的區域不會與float的元素區域重疊

  • 計算BFC的高度時,浮動子元素也參與計算

  • BFC就是頁面上的一個隔離的獨立容器,容器裡面的子元素不會影響到外面元素,反之亦然

BFC的作用

防止垂直 margin 重疊

同一個 BFC 下外邊距會發生摺疊

<style>
	div {
		width: 100px;
		height: 100px;
		background: lightblue;
		margin: 100px;
	}
</style>

<body>
    <div></div>
    <div></div>
</body>
複製程式碼

圖片載入失敗!

從效果上看,因為兩個 div 元素都處於同一個 BFC 容器下 (這裡指 body 元素) 所以第一個 div 的下邊距和第二個 div 的上邊距發生了重疊,所以兩個盒子之間距離只有 100px,而不是 200px。

首先這不是 CSS 的 bug,我們可以理解為一種規範,如果想要避免外邊距的重疊,可以將其放在不同的 BFC 容器中。

<style>
	div {
		width: 100px;
		height: 100px;
		background: lightblue;
		margin: 100px;
	}

	.container {
		overflow: hidden;
	}
</style>

<div class="container">
    <div></div>
</div>
<div class="container">
    <div></div>
</div>
複製程式碼

這時候,兩個盒子邊距就變成了 200px

圖片載入失敗!

清除元素內部浮動

浮動的元素會脫離普通文件流,

來看例子:

<style>
	.div1 {
		border: 1px solid #000;
	}

	.div2 {
		width: 100px;
		height: 100px;
		background: #eee;
		float: left;
	}
</style>  

<div class="div1">
	<div class="div2"></div>
</div>
複製程式碼

圖片載入失敗!

由於容器內元素浮動,脫離了文件流,所以容器只剩下 2px 的邊距高度。如果使觸發容器的 BFC,那麼容器將會包裹著浮動元素。

<style>
	.div1 {
		border: 1px solid #000;
		overflow: hidden;
	}

	.div2 {
		width: 100px;
		height: 100px;
		background: #eee;
		float: left;
	}
</style>

<div class="div1">
	<div class="div2"></div>
</div>
複製程式碼

圖片載入失敗!

阻止元素被浮動元素覆蓋

先來看一個文字環繞效果:

<style>
	.div1 {
		height: 100px;
		width: 100px;
		float: left;
		background: lightblue;
	}

	.div2 {
		width: 200px;
		height: 200px;
		background: #eee;
	}
</style>  

<div class="div1">
	我是一個左浮動的元素
</div>
<div class="div2">
	我是一個沒有設定浮動,也沒有觸發 BFC 元素。我是一個沒有設定浮動,也沒有觸發 BFC 元素。
</div>

複製程式碼

圖片載入失敗!

這時候其實第二個元素有部分被浮動元素所覆蓋(背景被覆蓋),(但是文字資訊不會被浮動元素所覆蓋) 如果想避免元素被覆蓋,可觸第二個元素的 BFC 特性,在第二個元素中加入 overflow: hidden,就會變成:

<style>
	.div1 {
		height: 100px;
		width: 100px;
		float: left;
		background: lightblue;
	}

	.div2 {
		width: 200px;
		height: 200px;
		background: #eee;
		overflow: hidden;
	}
</style>

<div class="div1">
	我是一個左浮動的元素
</div>
<div class="div2">
	我是一個沒有設定浮動,也沒有觸發 BFC 元素。我是一個沒有設定浮動,也沒有觸發 BFC 元素。
</div>
複製程式碼

圖片載入失敗!

這個方法可以用來實現兩列自適應佈局,這時候左邊的寬度固定,右邊的內容自適應寬度(去掉上面右邊內容的寬度)。


N_N

相關文章