BFC及其應用

前言

本文包括以下內容:

  • 什么是BFC
  • 如何產生BFC
  • BFC的特點
  • 應用BFC

1、什么是BFC

BFC (Block formatting contexts)塊級格式化上下文,首先看一下 w3c 是如何定義BFC的(大致翻譯如下):

浮動元素,絕對定位元素,非塊級盒子的塊級容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow不為 visiable 的塊級盒子,都會為他們的內容創建新的塊級格式化上下文。

在一個塊級格式化上下文中,盒子從頂端開始垂直地一個接一個地排列,兩個盒子之間的垂直的間隙是由他們的margin 值所決定的。在一個BFC中,兩個相鄰的塊級盒子的垂直外邊距會產生合并。

在塊級格式化上下文中,每一個盒子的左外邊緣(margin-left)會觸碰到容器的左邊緣(border-left)(對于從右到左的格式來說,則觸碰到右邊緣),即使存在浮動也是如此,除非這個盒子創建一個新的塊級格式化上下文。

可以這樣理解BFC:把BFC看作一個盒子(容器),這個BFC盒子有自己獨立的布局方式,一個BFC盒子中的元素布局不受外界影響,也不會影響到外面的元素。且在一個BFC中塊盒與行盒都會垂直排列,若存在外邊距則會產生外邊距合并。

2、如何產生BFC

在怎樣的條件下會產生塊級格式化上下文,這里引用部分 MDN關于BFC 的內容。

  • 浮動元素
  • 絕對定位的元素 (元素具有position為 absolute或 fixed)
  • 內聯塊 inline-blocks (元素具有 display: inline-block)
  • 表格單元格 、標題(元素具有 display: table-cell、table-caption,HTML表格單元格默認屬性)
  • 塊元素具有overflow且值不是 visible的

3、BFC的特點

  1. 同屬一個BFC的內容會發生外邊距合并(Margin Collapse),兩個外邊距大致可以分為下列三種情況:
  • 外邊距均為正值,取兩者中較大的數
  • 外邊距一正一負時,取兩者相加
  • 外邊距均為負時,取兩者中絕對值較大的
  1. BFC不會重疊浮動元素
  2. BFC可以包含浮動

4、應用BFC

  • 解決外邊距合并的問題。
    同屬一個BFC的內容會發生外邊距合并,那么,我們可以建立新的BFC,使得它們不屬于同一個BFC時則外邊距不會發生合并。
    外邊距合并問題1

    先是相鄰的兄弟元素外邊距合并,需要先給其中的一個盒子加上一個父元素,然后給這個父元素添加overflow:hidden,這一點很重要,可以理解為這個屬性是為其中的content新創建一個BFC,所以一開始在創建這個Demo的時候 我就有類似這樣的疑問:overflow:hidden 能觸發BFC,為什么不會阻止垂直外邊距疊加?
    外邊距合并解決1

    其實解決外邊距合并的方法其實有很多,個人覺得用BFC并不好,且麻煩,需要先創建一個父元素(因為直接給子元素.box2設置overflow: hidden是無效的)。當我嘗試使用另外一個方法: display: inline-block創建BFC的時候,發現并不需要創建父元素,外邊距會直接合并。
    外邊距合并解決2

    這時候我就遇到了這樣一個問題: 同樣是創建BFC,為什么使用overflow: hidden需要創建父元素,而使用display: inline-block不需要創建父元素呢?
    個人理解是這樣的:這些應用BFC的屬性,為它們的content創建了一個新的獨立計算區域(BFC),在這塊新的獨立計算區域中與外面元素的外邊距不產生重疊,而在這塊獨立計算區域之內仍然是外邊距重疊的。
    新的獨立計算區域

    而當使用display: inline-block觸發了別的外邊距合并的條件(可能是因為 IFC),并非因為BFC而發生合并。在下面的參考文章鏈接中也有指出那么一點:

inline-block元素不與任何元素的外邊距產生折疊

還可以參照下圖,可知應該是display: inline-block的問題使得外邊距計算直接相加,當我們再使用其它屬性,如display: table-cell的時候,仍然需要為這個元素創建父元素div.ct然后應用屬性,產生BFC才可以生效,而直接用在相鄰元素上是無效的。

外邊距合并解決3

  • 實現兩欄布局 及 去除文字環繞效果
    當存在兩個相鄰的div時,它們會垂直排列,但當給第一個元素設置float屬性時,則會發生盒子重疊。假設第一個盒子比第二個盒子大(否則覆蓋后就看不到第二個盒子)。在這里會首先發現這個文字并不會被浮動元素遮擋(現在是文字較少的情況,僅4個字符),當box1大于box2時,這個文字仍然不會被遮擋而是跑到盒子的右側或下側(據box2寬高決定)。

    floatBox1+ box2

    當文字較多時,所有的文字都會圍繞著box1,形成文字環繞效果。而給box2添加overflow:hidden;時則不會再發生文字環繞。這是之前提到的BFC特性當中的一點: * BFC 不會重疊浮動元素 *,當給box2添加屬性時,它就產生了新的BFC使得它不會再去重疊浮動的box1
    同理,當去除box2的寬度時,即可形成自適應的兩欄布局。
    去除文字環繞效果

  • 解決因為子元素浮動而帶來的父容器高度塌陷問題
    當一個父容器中的元素都設置為浮動,且自身沒有設置高度時,則父容器的高度就會發生塌陷(就好像沒有了子元素一樣)。如下圖中的 ① 過程。而給父元素設置了overflow: hidden;時則又發生了 ② 過程這樣的變化。這是因為這給父容器設置成了一個新的BFC,再結合之前的特性:BFC可以包含浮動 可知,就是因為這個BFC的生成使得高度不塌陷。(使用其它屬性如display: table-cell也可使得高度不塌陷)

    父容器高度塌陷

后記

使用BFC并不是很好的解決方案,像一個外邊距合并問題給人帶來的困擾就非常大,完全可以使用更簡單的方案 如給父元素添加透明的borderpadding來解決; 像是兩欄布局以及去除文字環繞效果,也可以通過margin-left來解決,使用overflow: hidden也會產生新的問題,如文字溢出無法顯示;最后一個更是可以使用清除浮動(添加.clearfix)來解決父元素高度塌陷。
這里使用BFC 僅僅是為了更好理解它而已 ~

參考文章:

深入理解BFC和Margin Collapse - w3cplus
BFC 神奇背后的原理

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 問答題47 /72 常見瀏覽器兼容性問題與解決方案? 參考答案 (1)瀏覽器兼容問題一:不同瀏覽器的標簽默認的外補...
    _Yfling閱讀 13,809評論 1 92
  • 一、在什么場景下會出現外邊距合并?如何合并?如何不讓相鄰元素外邊距合并?給個父子外邊距合并的范例 在CSS當中,相...
    dengpan閱讀 603評論 0 0
  • relative:生成相對定位的元素,通過top,bottom,left,right的位置相對于其正常位置進行定位...
    zx9426閱讀 968評論 0 2
  • 1.在什么場景下會出現外邊距合并?如何合并?如何不讓相鄰元素外邊距合并?給個父子外邊距合并的范例 概念:在CSS當...
    饑人谷_任磊閱讀 711評論 0 3
  • 在什么場景下會出現外邊距合并?如何合并?如何不讓相鄰元素外邊距合并?給個父子外邊距合并的范例塊元素直接接觸的垂直外...
    老虎愛吃母雞閱讀 472評論 0 0