[翻譯] 理解 CSS 佈局和塊級格式上下文

tumars發表於2019-02-28

注:本文首發於個人部落格 www.ferecord.com/understandi…,如若轉載請註明來源。

前言

BFC 的概念始於 CSS2,是個蠻古老的 CSS 話題了,網上也到處能搜到 BFC 的介紹,但是都不夠簡潔。本文系翻譯自 Rachel Andrew 女士的博文 Understanding CSS Layout And The Block Formatting Context,內容足夠簡潔明瞭。

本文的目的是介紹一些概念,來幫你增強 CSS 碼力。如標題所示,這篇文章主要是講塊級格式上下文(BFC,Block Formatting Context)。你可能沒聽過這個術語,但只要你曾經使用 過CSS 佈局,你就能明白它。理解 BFC 是什麼、它如何工作、如何建立一個 BFC 是非常有用的,這些能幫你更好的理解 CSS 佈局。

這篇文章裡,我會通過幾個你會很熟悉的的示例解釋 BFC。我還會告訴你一個新的 display 值,當你理解了 BFC 後可能會很需要這個值。

什麼是 BFC

一個簡單的浮動的示例就能明白 BFC 的行為,在下面的示例中我們建立一個 box 元素,該元素包裹一段文字和一個浮動的圖片。 如果文字內容多的話文字將環繞著整個浮動圖片,box 的邊框會把他們整個包裹起來。

<div class="outer">
	<div class="float">I am a floated element.</div>
	I am text inside the outer box.
</div>
複製程式碼
.outer {
      border: 5px dotted rgb(214,129,137);
      border-radius: 5px;
      width: 450px;
      padding: 10px;
      margin-bottom: 40px;
}

.float {
      padding: 10px;
      border: 5px solid rgba(214,129,137,.4);
      border-radius: 5px;
      background-color: rgba(233,78,119,.4);
      color: #fff;
      float: left;  
      width: 200px;
      margin: 0 20px 0 0;
}
複製程式碼

[翻譯] 理解 CSS 佈局和塊級格式上下文
文字環繞著浮動元素

但如果把一些文字刪除,就沒有足夠的文字去環繞圖片(浮動元素)了,同時由於浮動元素脫離文件流,box 元素的邊框高度就會隨文字的減少而降低。

[翻譯] 理解 CSS 佈局和塊級格式上下文
沒有足夠的文字,box 元素邊框的高度就會低於浮動元素的高度

之所以會發生這種情況是由於當我們浮動一個元素後,box 元素仍然保持原來的寬度,是文字所佔的空間縮短了以給浮動元素騰出位置,這就是為什麼背景和邊框能夠看起來包裹住了浮動元素。

我們通常會使用兩種不同的方式來解決這個問題,一種是使用 clear hack,就是在 文字和圖片的下方插入一個 div 並將它的 CSS clear 屬性設值為 both。另外一種方法是使用 overflow 屬性 ,把它設值成非預設值 visible 的值。

.outer {
      overflow: auto;
}
複製程式碼

[翻譯] 理解 CSS 佈局和塊級格式上下文
使用 overflow: auto 後 box 就能包裹浮動元素了

overflow 之所以能夠有效是因為當它的是是非 visible 時會建立一個 BFC,而 BFC 的功能之一就是包裹浮動元素

BFC 是佈局中的迷你佈局

你可以把 BFC 當做你頁面中的一塊小布局,當一個元素被建立成 BFC 後,它其中的所有元素都會被它包裹。正如我們所見,當 box 元素變成 BFC 後,它其中的浮動元素就再也沒能突破它的底部。除此之外,BFC 還有一些有用的功能。

BFC 可以阻擋外邊距疊加(margins collapsing)

理解外邊距疊加是另外一個被低估的 CSS 技巧。在接下來的示例裡,我建立了一個背景灰色的 div,這個 div 含有兩個段落,div 元素的 margin-bottom 為 40px,同時每個段落都有 20px 的 margin-top 與 margin-bottom。

.outer {
       background-color: #ccc;
      margin: 0 0 40px 0;
}

p {
      padding: 0;
      margin: 20px 0 20px 0;
      background-color: rgb(233,78,119);
      color: #fff;
}
複製程式碼

由於 p 元素的邊緣與 outer 元素的邊緣之間沒有任何東西,所以 outer 與 p 的 margin 會疊加,p 會與 outer 的頂部與底部齊平,p 對外的 margin 似乎與 outer 的 margin 合併了,使我們無法在段落的上下看到 outer 的灰色背景。

[翻譯] 理解 CSS 佈局和塊級格式上下文
由於 margin collapse(外邊距疊加),我們看到 outer 內部上下沒有灰色背景

如果我們把 outer 元素變成 BFC,它就可以包裹住 p 以及 p 的 margin,外邊距不會發生疊加,outer 元素內部就會出現由 p 元素的 margin 頂出來的上下灰色背景。

.outer {
       background-color: #ccc;
      margin: 0 0 40px 0;
      overflow: auto;
}
複製程式碼

[翻譯] 理解 CSS 佈局和塊級格式上下文
建立 BFC 後,外邊距不再疊加

一旦 BFC 建立,它就會阻止它內部的元素逃離突破它。

一個 BFC 會停止去環繞浮動元素

你可能很熟悉 BFC 的這個特性,我們在有浮動元素的列型別佈局中常用到。如果一個元素建立了 BFC,它就不會去環繞(或者說包裝?)任何浮動元素。看下面這個示例:

<div class="outer">
      <div class="float">I am a floated element.</div>
      <div class="text">I am text</div>
</div>
複製程式碼

class 名為 float 的元素將會浮動在佈局的左側,class 名為 text 的 div 元素將會在它後面並環繞它。

[翻譯] 理解 CSS 佈局和塊級格式上下文
文字環繞著浮動元素

我們可以通過給 text 元素建立 BFC 來阻擋這種環繞行為。

.text {
      overflow: auto;
}
複製程式碼

[翻譯] 理解 CSS 佈局和塊級格式上下文
text 元素建立 BFC 後就不再環繞浮動元素了

該方法也是我們建立浮動佈局的基本方式。還需注意的是浮動一個元素時也會給該元素建立 BFC,也就是說此時 .float 與 .text 都是 BFC,這也是無論右側高度低於還是高於左側兩者都不會互相圍繞的原因。

建立一個 BFC 的常用方式

除了使用 overflow 外, 一些其他的 CSS 屬性也可以建立 BFC,比如上面我們所見,浮動一個元素也可以為該元素建立 BFC,浮動元素會包裹它內部的所有元素。還有以下幾種方式可以建立 BFC:

使用 position: absolute 或者 position: fixed

使用 display: inline-blockdisplay: table-cell 或者 display: table-caption,其中 table-celltable-caption是表格相關 HTML 元素的對應預設 CSS 值,所以當你建立表格每個表格單元都會自動建立 BFC。

另外當使用 multi-column layout (多列布局)時使用 colum-span: all 也可以建立 BFC。Flex(彈性) 和 Grid(網格) 佈局中的元素也會自動建立類似 BFC 的機制,只是它們被稱為 Flex Formatting Context(彈性格式上下文)和 Grid Formatting Context(網格格式上下文)。這反映了它們所參與的佈局型別。一個 Block Formatting Context(塊級格式上下文)表明他內部的元素參與了塊級佈局,一個 彈性格式上下文意味著它內部的元素參與了彈性佈局。在實踐中,這幾種佈局的結果是相似的,浮動元素會被包裹、外邊距不會疊加。

建立 BFC 的新方式

使用 overflow 或其他的方法建立 BFC 時會有兩個問題。第一個是這些方法本身是有自身的設計目的的,所以在使用它們建立 BFC 時會可能產生副作用。例如使用 overflow 建立 BFC 後在某些情況下你可能會看到出現一個滾動條或者元素內容被削減。這是由於 overflow 屬性是設計被用來讓你告訴瀏覽器如何定義元素的溢位狀態的。瀏覽器執行了它最基本的定義。

另一個問題是,即使在沒有出現副作用的情況下,使用 overflow 也可能會使另一個開發人員感到困惑。他們可能會各種猜想:這裡為啥要把 overflow 的值設為 auto 或 scroll?原開發人員做這個意義何在?原開發人員是想讓這裡出現滾動條嗎?

最安全的做法應該是建立一個 BFC 時不會有任何副作用,它內部的元素都安安全全的呆在這個小布局裡,這種方法不會引起任何意想不到的問題,也可以讓開發者意圖清晰。CSS 工作組也十分認同這種想法,所以他們定製了一個新的屬性值:display: flow-root

你可以使用 display: flow-root 安全的建立 BFC 來解決本文中提到的各種問題,包括:包裹浮動元素、阻止外邊距疊加、阻止環繞浮動元素。

[翻譯] 理解 CSS 佈局和塊級格式上下文
caniuse 上 display: flow-root 各瀏覽器支援情況

瀏覽器對該屬性值的支援目前還是有限的,如果你覺得這個屬性值很方便,請投票去讓 Edge 也支援它。不過無論如何,你現在應該已經理解了什麼是 BFC,以及如何使用 overflow 或其他方法來包裹浮動,以及知道了 BFC 可以阻止元素去環繞浮動元素,如果你想使用彈性或網格佈局可以在一些不支援他們的瀏覽器中使用 BFC 的這些特性做降級處理。

理解瀏覽器如何佈置網頁是非常基礎的。 雖然有時看起來無關緊要,但是這些小知識可以加快建立和除錯 CSS 佈局所需的時間。

相關文章