本文的目的是介紹一些概念來幫你增強 CSS 碼力。如标題所示這篇文章主要是講塊級格式上下文BFCBlock Formatting Context。你可能沒聽過這個術語但隻要你曾經使用 過CSS 布局你就能明白它。了解 BFC 是什麼、它如何工作、如何建立一個 BFC 是非常有用的這些能幫你更好的了解 CSS 布局。
這篇文章裡我會通過幾個你會很熟悉的的示例解釋 BFC。我還會告訴你一個新的 display 值當你了解了 BFC 後可能會很需要這個值。
<a href="http://www.ferecord.com/understanding-css-layout-block-formatting-context.html#_1">前言</a>
<a href="http://www.ferecord.com/understanding-css-layout-block-formatting-context.html#_2">目錄</a>
<a href="http://www.ferecord.com/understanding-css-layout-block-formatting-context.html#bfc">什麼是 BFC</a>
<a href="http://www.ferecord.com/understanding-css-layout-block-formatting-context.html#bfc_1">BFC 是布局中的迷你布局</a>
<a href="http://www.ferecord.com/understanding-css-layout-block-formatting-context.html#bfc_2">建立一個 BFC 的常用方式</a>
<a href="http://www.ferecord.com/understanding-css-layout-block-formatting-context.html#bfc_3">建立 BFC 的新方式</a>
一個簡單的浮動的示例就能明白 BFC 的行為在下面的示例中我們建立一個 box 元素該元素包裹一段文字和一個浮動的圖檔。 如果文字内容多的話文字将環繞着整個浮動圖檔box 的邊框會把他們整個包裹起來。
1
2
3
4
5
6
<div class="outer">
<div class="float">I am a floated element.</div>
I am text inside the outer box.
</div>
7
8
9
10
11
12
13
14
15
16
17
18
19
20
.outer {
border: 5px dotted rgb(214,129,137);
border-radius: 5px;
width: 450px;
padding: 10px;
margin-bottom: 40px;
}
.float {
border: 5px solid rgba(214,129,137,.4);
background-color: rgba(233,78,119,.4);
color: #fff;
float: left;
width: 200px;
margin: 0 20px 0 0;

文字環繞着浮動元素
但如果把一些文字删除就沒有足夠的文字去環繞圖檔浮動元素了同時由于浮動元素脫離文檔流box 元素的邊框高度就會随文字的減少而降低。
沒有足夠的文字box 元素邊框的高度就會低于浮動元素的高度
之是以會發生這種情況是由于當我們浮動一個元素後box 元素仍然保持原來的寬度是文字所占的空間縮短了以給浮動元素騰出位置這就是為什麼背景和邊框能夠看起來包裹住了浮動元素。
overflow: auto;
使用 <code>overflow: auto</code> 後 box 就能包裹浮動元素了
overflow 之是以能夠有效是因為當它的是是非 <code>visible</code> 時會建立一個 BFC而 BFC 的功能之一就是包裹浮動元素。
你可以把 BFC 當做你頁面中的一塊小布局當一個元素被建立成 BFC 後它其中的所有元素都會被它包裹。正如我們所見當 box 元素變成 BFC 後它其中的浮動元素就再也沒能突破它的底部。除此之外BFC 還有一些有用的功能。
BFC 可以阻擋外邊距疊加margins collapsing
了解外邊距疊加是另外一個被低估的 CSS 技巧。在接下來的示例裡我建立了一個背景灰色的 div這個 div 含有兩個段落div 元素的 margin-bottom 為 40px同時每個段落都有 20px 的 margin-top 與 margin-bottom。
background-color: #ccc;
margin: 0 0 40px 0;
p {
padding: 0;
margin: 20px 0 20px 0;
background-color: rgb(233,78,119);
由于 p 元素的邊緣與 outer 元素的邊緣之間沒有任何東西是以 outer 與 p 的 margin 會疊加p 會與 outer 的頂部與底部齊平p 對外的 margin 似乎與 outer 的 margin 合并了使我們無法在段落的上下看到 outer 的灰色背景。
由于 margin collapse外邊距疊加我們看到 outer 内部上下沒有灰色背景
如果我們把 outer 元素變成 BFC它就可以包裹住 p 以及 p 的 margin外邊距不會發生疊加outer 元素内部就會出現由 p 元素的 margin 頂出來的上下灰色背景。
建立 BFC 後外邊距不再疊加
一旦 BFC 建立它就會阻止它内部的元素逃離突破它。
一個 BFC 會停止去環繞浮動元素
你可能很熟悉 BFC 的這個特性我們在有浮動元素的列類型布局中常用到。如果一個元素建立了 BFC它就不會去環繞或者說包裝任何浮動元素。看下面這個示例
<div class="text">I am text</div>
class 名為 float 的元素将會浮動在布局的左側class 名為 text 的 div 元素将會在它後面并環繞它。
我們可以通過給 text 元素建立 BFC 來阻擋這種環繞行為。
.text {
text 元素建立 BFC 後就不再環繞浮動元素了
該方法也是我們建立浮動布局的基本方式。還需注意的是浮動一個元素時也會給該元素建立 BFC也就是說此時 .float 與 .text 都是 BFC這也是無論右側高度低于還是高于左側兩者都不會互相圍繞的原因。
除了使用 <code>overflow</code> 外 一些其他的 CSS 屬性也可以建立 BFC比如上面我們所見浮動一個元素也可以為該元素建立 BFC浮動元素會包裹它内部的所有元素。還有以下幾種方式可以建立 BFC
使用 <code>position: absolute</code> 或者 <code>position fixed</code>。
使用 <code>display: inline-block</code>、<code>display: table-cell</code> 或者 <code>display: table-caption</code>其中 <code>table-cell</code> 和 <code>table-caption</code>是表格相關 HTML 元素的對應預設 CSS 值是以當你建立表格每個表格單元都會自動建立 BFC。
另外當使用 multi-column layout 多列布局時使用 <code>colum-span: all</code> 也可以建立 BFC。Flex彈性 和 Grid網格 布局中的元素也會自動建立類似 BFC 的機制隻是它們被稱為 Flex Formatting Context彈性格式上下文和 Grid Formatting Context(網格格式上下文)。這反映了它們所參與的布局類型。一個 Block Formatting Context塊級格式上下文表明他内部的元素參與了塊級布局一個 彈性格式上下文意味着它内部的元素參與了彈性布局。在實踐中這幾種布局的結果是相似的浮動元素會被包裹、外邊距不會疊加。
使用 overflow 或其他的方法建立 BFC 時會有兩個問題。第一個是這些方法本身是有自身的設計目的的是以在使用它們建立 BFC 時會可能産生副作用。例如使用 overflow 建立 BFC 後在某些情況下你可能會看到出現一個滾動條或者元素内容被削減。這是由于 overflow 屬性是設計被用來讓你告訴浏覽器如何定義元素的溢出狀态的。浏覽器執行了它最基本的定義。
另一個問題是即使在沒有出現副作用的情況下使用 overflow 也可能會使另一個開發人員感到困惑。他們可能會各種猜想這裡為啥要把 overflow 的值設為 auto 或 scroll原開發人員做這個意義何在原開發人員是想讓這裡出現滾動條嗎
最安全的做法應該是建立一個 BFC 時不會有任何副作用它内部的元素都安安全全的呆在這個小布局裡這種方法不會引起任何意想不到的問題也可以讓開發者意圖清晰。CSS 工作組也十分認同這種想法是以他們定制了一個新的屬性值<code>display: flow-root</code>。
你可以使用 <code>display: flow-root</code> 安全的建立 BFC 來解決本文中提到的各種問題包括包裹浮動元素、阻止外邊距疊加、阻止環繞浮動元素。
caniuse 上 display: flow-root 各浏覽器支援情況
浏覽器對該屬性值的支援目前還是有限的如果你覺得這個屬性值很友善請投票去讓 Edge 也支援它。不過無論如何你現在應該已經了解了什麼是 BFC以及如何使用 overflow 或其他方法來包裹浮動以及知道了 BFC 可以阻止元素去環繞浮動元素如果你想使用彈性或網格布局可以在一些不支援他們的浏覽器中使用 BFC 的這些特性做降級處理。
了解浏覽器如何布置網頁是非常基礎的。 雖然有時看起來無關緊要但是這些小知識可以加快建立和調試 CSS 布局所需的時間。