BFC 是什么?从没有认识到最初的认识是一个关键且困难的过程。网上的很多文章都会写道:BFC 是一个环境。这样的写法让人看了就头疼:我们在 HTML 和 CSS 中好像从没接触过环境这个概念。

下面不妨让我用通俗的方式解释一下 BFC 的概念:BFC 可以简单的理解为某个元素的一个 CSS 属性,只不过这个属性不能被开发者显式的修改,拥有这个属性的元素对内部元素和外部元素会表现出一些特性(后面会讲到),这就是 BFC。

BFC 的特性

BFC 对布局的影响主要体现在对 float 和 margin 两个属性的处理。在我看来,BFC 让 float 和 margin 这两个属性的表现更加符合我们的直觉。

BFC 包裹浮动元素

BFC 的特性之一就是其高度的计算会包括所有浮动元素的高度,所以使用 BFC 可以包裹浮动元素,达到清除浮动的目的。

<div style="overflow: hidden; background: #AAA;">
  <div
    style="float: left; width: 100px; height: 100px; background: #000;"
  ></div>
</div>

overflow: hidden可以触发一个元素的 BFC 属性,使该元素成为一个 BFC 容器,从而使该元素对内部元素及外部元素表现出 BFC 的特性

运行代码可以看到,我们虽然没有进行任何清除浮动的工作,外层 div 还是包裹住了内层浮动的 div,没有造成高度塌陷的情况。

另外,将外层 div 同时设为浮动来清除内层浮动的方法,本质上也是应用了 BFC 的特性,因为将一个元素设为浮动也会触发该元素的 BFC 属性,使外层元素成为一个 BFC 容器。

BFC 包裹 margin(阻止外边距折叠)

BFC 对内部元素的另一个特性就是可以取消 margin 折叠(margin collapse)。这个特性我喜欢更形象的称之为包裹 margin。

<div style="background: #AAA;">
  <div
    style="width: 100px; height: 100px; margin-top: 50px; background: #000;"
  ></div>
</div>

运行代码可以看到,内层 div 的 margin 并没有将内层 div 相对于外层 div 向下推移,而是将内外两层 div 整体向下推移:

而我们想要的结果是这样的:

内外两层 div 被整体向下推移的原因就是 margin 折叠,关于 margin 折叠的相关介绍可以参见这里。CSS 中父子元素的 margin 只要相邻,也会发生折叠,CSS 规范虽是如此,但很多时候这并不符合我们的预期:我们希望外部 div 能够包裹内部 div 的 margin,避免形成折叠,这时我们就可以使用 BFC。

<div style="overflow:hidden; background:#AAA;">
  <div
    style="width:100px; height:100px; margin-top:50px; background:#000;"
  ></div>
</div>

我们将外层 div 设置为一个 BFC 容器,由于 margin 折叠只会发生在同一个 BFC 中的元素之间,而不同 BFC 的元素之间以及元素及其所属的 BFC 之间不会发生 margin 折叠,因此就可以实现对 margin 的包裹。

BFC 可以阻止元素被浮动元素覆盖,阻止文本在浮动元素周围自动换行

BFC 对外部元素的独立性在于 BFC 元素不会与浮动元素叠加。例如:

<div style="float: left; width: 100px; height: 100px; background: #000;"></div>
<div style="height: 200px; background: #AAA;"></div>


可以看到,浮动的 div 由于脱离了文档流,导致正常的 div 左上角被覆盖。为了避免这种情况,我们使第二个 div 成为 BFC 容器:

<div style="float: left; width: 100px; height: 100px; background: #000;"></div>
<div style="overflow: hidden; height: 200px; background: #AAA;"></div>


当第二个 div 成为 BFC 容器后,其不会再受到浮动 div 的影响,布局相对独立。这样的技巧经常用作两栏或三栏自适应布局。

BFC 的触发条件

BFC 可以被理解为元素的一个属性,但是这个属性无法被显式的设置,那么如何触发一个元素的 BFC 属性呢?上面的代码中使用的 overflow:hidden 就是触发 BFC 的一种方式,除了设置 overflow:hidden,下面的 CSS 属性设置都可以触发 BFC:

  • 父级元素,浮动元素:float 设置为除 none 之外的取值;
  • 父级元素的 overflow 设置为除 visible 之外的取值;
  • 父级元素,绝对定位元素:position 设置为 absolute 或 fixed;
  • 父级元素,display 设置为 table-cell、table-caption、inline-block 中的任一取值;

BFC 与 Layout

IE 作为浏览器中的奇葩,当然不可能按部就班的支持 BFC 标准,于是乎 IE 中有了 Layout 这个东西。Layout 和 BFC 基本是等价的,为了处理 IE 的兼容性,在需要触发 BFC 时,我们除了需要用上面的 CSS 属性来触发 BFC,还需要针对 IE 浏览器使用zoom: 1来触发 IE 浏览器的 Layout。

参考链接:理解 CSS 中 BFC