編碼的世界 / 優質文選 / 生涯

CSS基礎:CSS的上下文之BFC


2022年4月21日
-   

CSS的上下文之BFC
看到這個名詞,可能會有些陌生,但其實 上下文 = 區域,如果這麼理解的話就會有行級上下文、塊級上下文、flex上下文等等有一定排列規則的區域,我們今天只聊一聊 塊級格式化上下文(BFC)

一、什麼是BFC?


BFC全稱”Block Formatting Context”, 中文為“塊級格式化上下文”。是Web頁面的可視CSS渲染的一部分,是塊盒子的布局過程發生的區域,也是浮動元素與其他元素交互的區域。
下列方式會創建塊格式化上下文(列舉常見的方式):
  • 根元素(<html>
  • 浮動元素(元素的 float 不是 none)
  • 絕對定位元素(元素的 position 為 absolute 或 fixed)
  • display 為 inline-block、table-cells、flex
  • overflow 計算值不為 visible 的塊元素

塊格式化上下文包含創建它的元素內部的所有內容。
整理一下:BFC屬於普通的文檔流,具有 BFC 特性的元素可以看作是隔離了的獨立容器,容器裏面的元素不會在布局上影響到外面的元素,它有一套渲染規則,它決定了其子元素將如何定位,以及和其他元素的關系和相互作用。

二、BFC的特點以及應用


2.1 同一個BFC下,外邊距會發生折疊
來看這樣一段代碼:
.box{
width: 300px;
}
.child{
margin: 100px;
width: 100px;
height: 100px;
background: rgb(95, 172, 182);
}

<div class="box">
<div class="child"></div>
<div class="child"></div>
</div>

現象:明明兩個child都存在100px的外邊距,但他們實際間隔卻不是200px,而是100px,這算是一種合並“規則”,當你發現你的頁面因為加入了margin而出現了奇怪的問題,不妨往合並的方向思考
解釋:同一個BFC中,相鄰的兄弟元素之間的相對的margin-bottom和margin-top會進行合並,並且顯示的是較大值。
解決與注意:想要解決這樣的問題,我們可以通過將兩個child放置於不同的BFC中,直接上圖:
下圖通過BFC解決了問題,是否產生了新的問題?是否可以通過其他方式解決呢?希望大家能靈活選擇噢~
2.2 解決父子元素之間margin塌陷問題
來看這樣一段代碼:
body{
background: #ccc;
}
.box{
margin: 100px;
width: 300px;
height: 300px;
background: rgb(149, 98, 98);
}
.child{
margin: 50px;
width: 100px;
height: 100px;
background: rgb(95, 172, 182);
}

<div class="box">
<div class="child"></div>
</div>


現象:
  • box元素存在外邊距100px,相對於body的效果生效了,毫無疑問;
  • child元素存在外邊距50px,相對於box的效果僅左側生效了,存在疑問;

解釋:有了2.1小節的經驗,大家會猜測是不是margin再次發生了合並?也可以,但更合理的形容叫 “margin塌陷”
父子相鄰嵌套的元素在垂直方向的margin會發生塌陷,並取最大值。
拿例子中的box元素舉例,box作為頂,子元素向外稱起50px卻失效了,可以理解為頂塌陷了。
如果子元素的margin-top = 200px 會發生什麼呢?
解決與注意:通過觸發BFC,你可以解決當下的問題,但是請思考,子元素的是否需要margin來實現間距,給box元素添加padding會不會更好一些?
2.3 BFC 可以包含浮動的元素(清除浮動)
我們都知道,浮動的元素會脫離普通文檔流,來看下下面一個例子:
.box{
border: 1px solid black;
}
.child{
width: 100px;
height: 100px;
background: #ddd;
float: left;
}

<div class="box">
<div class="child"></div>
</div>


現象:
  • child因為浮動,脫離了文檔流;
  • box盒子的高度只計算了border;

解釋:
  • 因為子元素已經脫離了文檔流,所以父元素在計算高度時忽略了它;

解決:觸發容器的 BFC,使得容器包裹著浮動元素。

2.4 BFC 解決文字環繞的問題
浮動的目的。最初時,浮動只能用於圖像(某些瀏覽器還支持表的浮動),目的就是為了允許其他內容(如文本)“圍繞”該圖像。而後來的CSS允許浮動任何元素。
body {
padding: 100px;
}
.box {
border: 1px solid black;
width: 300px;
background: #ddd;
}
.left {
width: 100px;
height: 100px;
float: left;
background: rgb(81, 196, 204);
}

<div class="box">
<div class="left"></div>
<div class="right">
解決文字環繞的問題, 解決文字環繞的問題, 解決文字環繞的問題, 解決文字環繞的問題
解決文字環繞的問題, 解決文字環繞的問題, 解決文字環繞的問題, 解決文字環繞的問題
</div>
</div>

現象:
  • 給左側子元素設置了左浮動,使得文字環繞在它周圍,但為什麼文字會被環繞,而不是被遮擋?

解釋:
看到float會脫離文檔流,這是相對於盒子模型來說的。但它沒有脫離文本流。
  • 文檔流是相對於盒子模型講的
  • 文本流是相對於文子段落講的

元素浮動之後,會讓它脫離文檔流,也就是說當它後面還有元素時,其他元素會無視它所占據了的區域,直接在它身下布局。但是文字卻會認同浮動元素所占據的區域,圍繞它布局,也就是沒有脫離文本流。
在MDN上提到,該元素從網頁的正常流動(文檔流)中移除,盡管仍然保持部分的流動性(與絕對定位相反)。
解決將包裹文字的元素置為BFC,看圖:

問題解決了,新知識又增加了,例如自適應兩欄布局,請看下圖:

寫在最後


《CSS基礎系列》第四篇文章
如果對你有所幫助不妨給本項目的github 點個 star,這是對我最大的鼓勵!
關於我
  • 花名:餘光
  • WX:j565017805
  • 沉迷 JS,水平有限,虛心學習中

其他沉澱
  • Github: Js版LeetCode題解
  • 前端進階筆記
  • CSS 基礎

熱門文章