細說CSS中的BFC

滴滴出行·DDFE發表於2016-11-28

作者:滴滴公共前端團隊 - 邱蓮

BFC是什麼?

BFC(Block Formatting Context)直譯為“塊級格式化範圍”。

是 W3C CSS 2.1 規範中的一個概念,它決定了元素如何對其內容進行定位,以及與其他元素的關係和相互作用。當涉及到視覺化佈局的時候,Block Formatting Context提供了一個環境,HTML元素在這個環境中按照一定規則進行佈局。一個環境中的元素不會影響到其它環境中的佈局。

比如浮動元素會形成 BFC,浮動元素內部子元素的主要受該浮動元素影響,兩個浮動元素之間是互不影響的。這裡有點類似一個 BFC 就是一個獨立的行政單位的意思。

也可以說 BFC 就是一個作用範圍。可以把它理解成是一個獨立的容器,並且這個容器的裡box的佈局,與這個容器外的毫不相干。

BFC 的特徵:

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

  • Box垂直方向的距離由margin決定。屬於同一個BFC的兩個相鄰Box的margin會發生重疊

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

  • BFC的區域不會與float box重疊。

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

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

BFC 的應用場景有哪些?如何觸發 BFC?

滿足下列條件中至少一項,即可觸發 BFC:

  1. float 的值不為none。

  2. position 的值不為static或者relative。

  3. display的值為 table-cell, table-caption, inline-block, flex, 或者 inline-flex中的其中一個。

  4. overflow的值不為visible。

BFC 的應用場景:

1.解決 margin 疊加問題:

<div class="first-block"></div>
<div class="second-block">
    <h2>DDFE</h2>
</div>複製程式碼
.first-block {
    background: #F44336;
    width: 200px;
    height: 200px;
}
.second-block {
    background: #00BCD4;
    width: 200px;
    height: 200px;
}複製程式碼

很簡單是吧,瀏覽器中的效果是這樣的:

細說CSS中的BFC

為什麼 first-block 和 second-block 之間會有這麼寬的間距?

原因是:外邊距摺疊,這個間距是 h2 的上外邊距引起的

CSS 裡面關於摺疊的條件:

兩個塊元素要產生摺疊現象,必須滿足一個必備條件:這兩個元素的 margin 必須是 相鄰 的;那麼如果定義相鄰呢,w3c 規範,兩個 margin 是鄰接的必須滿足以下條件:

  • 必須是處於常規文件流(非float和絕對定位)的塊級盒子,並且處於同一個 BFC 當中。

  • 沒有inline盒子,沒有空隙,沒有 padding 和 border 將他們分隔開。

  • 都屬於垂直方向上相鄰的外邊距,可以是下面任意一種情況:

那麼我們就可以通過給元素叫邊框或者邊距來解決啦,我是不是狠聰明呢?

解決辦法 1:

細說CSS中的BFC

摺疊問題解決了,但是由於有1px的邊框,second-block 看起來會比 first-block 寬一點,沒關係,新增 box-sizing: border-box 屬性可以解決這個問題:再加一句:box-sizing:border-box ;

解決辦法 2:

細說CSS中的BFC

通過把 overflow 把 second-block 元素形成一個 BFC,完美解決!

2.用於佈局

杯佈局和雙飛翼佈局,他們的都要求三列布局,中間寬度自適應,兩邊定寬,這樣做的優勢是重要的東西放在文件流前面可以優先渲染。
樣子,就長這樣:

細說CSS中的BFC

老規矩先貼上程式碼:
html部分:
細說CSS中的BFC

css部分:
細說CSS中的BFC

  1. html程式碼中,middle部分首先要放在container的最前部分,然後是left,right 。
  2. 將三者都設定 float:left, position:relative
  3. middle設定 width:100% 佔滿一行 。
  4. 此時middle佔滿一行,所以要把left拉到middle所在行的最左邊,使用 margin-left:-100%
  5. 這時left拉回到middle所在行的最左邊,但會覆蓋middle內容的左端,要把middle內容拉出來,所以在外圍container加上 padding:0 200px
  6. middle內容拉出來了,但left也跟著出來了,所以要還原,就對left使用相對定位 left:-200px
  7. 同理,right要拉到middle所在行的最右邊,使用 margin-left:-200pxright:-200px

其實除了聖盃佈局還有一個雙飛翼佈局,雙飛翼佈局是對聖盃佈局的一種改良,多一個div就可以不用相對佈局了,只用到了浮動和負邊距。

DOM結構:container內層增加了一個div

細說CSS中的BFC

樣式:去掉了左右欄的相對定位,去掉包裹層padding,以中間欄新增div的margin代替。

細說CSS中的BFC

是不是很簡單?

3.用於清除浮動,計算BFC高度

舉個例子:

細說CSS中的BFC

我們想象中應該是這樣的:

細說CSS中的BFC

但實際是卻是這樣的:

細說CSS中的BFC

div 標籤沒有包住 ul 標籤,原因很簡單:container 下的子元素浮動了,因此div的高度就塌陷了。
要解決塌陷,就得清除浮動。

清除浮動就兩種方式:

1)利用 clear 屬性清除浮動。

細說CSS中的BFC

2)使父容器形成 BFC

給父元素 .container 加一句 overflow:hidden 觸發 bfc。


歡迎關注DDFE
GITHUB:github.com/DDFE
微信公眾號:微信搜尋公眾號“DDFE”或掃描下面的二維碼

細說CSS中的BFC

相關文章