人人都懂 BFC (块格式化上下文)

1,620 阅读5分钟

引言

看了那么多关于 BFC 的文章,但是没有几篇能简单明了的说清楚。于是,我查阅规范重新整理了一遍。尽量使用较少的概念和术语,解释清楚 BFC 为什么能消除外边距折叠、处理浮动引起的高度塌陷。

视觉格式化模型

视觉格式化模型(Visual formatting model)规定了浏览器如何访问文档树。换句话说,就是如何把DOM树渲染成网页。在视觉格式化模型中,规定了每一个元素(document element)如何生成一个或多个盒子(参考盒模型)。比如:

  • 盒子尺寸和类型
  • 定位方案(正常文档流、浮动和绝对定位)
  • 文档树中元素之间的关系
  • 外部信息(例如,视口大小、图像的固有尺寸等)

块格式化上下文

BFCblock formatting context 的简称,翻译过来就是块格式化上下文,是视觉格式化模型中一个术语,其有一套相关约束规则,规定了块级盒子内部如何布局排版。可以理解它为视觉格式化模型的某个场景实现方案。除此之外,还有 inline formatting contextflex formatting context 等。

浮动、绝对地定位(absolute、fixed)元素、块容器(比如:inline-block、table-cells、table-captions),以及 overflow 不为 visible 的块级盒子会产生一个新的独立的 BFC。(如果没有刻意说明,以下提到 BFC 默认为独立的格式化上下文)

在 BFC 中,从内容区域顶部开始,(块级)盒子会贴着内容区域左边(从右往左格式化,就是贴着右边)一个挨一个垂直排列。相邻的两个盒子,其垂直方向的外边距会发生折叠。如果盒子前面有浮动元素,其左边依然也会贴着内容区域的左边。除非这个盒子产生了新的块格式化上下文,那么它的左边就不再贴着内容区域的左边了。这个时候会由于浮动元素,自动宽度块级盒子会被压缩。[BFC官方文档]

独立格式化上下文

以上两段描述了 BFC 是如何产生的,以及其内部布局特性。这些还不够完全了解 BFC。于是,在 CSS3 Display Module 规范中又做了一些关于独立格式化上下文的补充说明以及 BFC 的例子。

当一个盒子(box)建立了一个独立的格式上下文(无论该格式上下文是否与其父级相同)时,它本质上创建了一个新的、独立的布局环境:除非通过调整盒子本身的大小,否则其内部的布局(通常)是不受盒子外格式化上下文的规则和内容的影响,反之亦然。但是也有例外,有兴趣的同学可以看看 [CSS3-EXCLUSIONS]

例如,在块格式化上下文中,浮动元素会影响周围元素的布局。但它们的影响并没有脱离其格式化上下文:建立其格式化上下文的元素会增长到完全包含它们,并且不允许内外浮动元素互相影响。

BFC 使用场景&原理

使用 BFC 解决网页布局遇到的问题,始终要记住一个词:隔离。就像生死隔离一样,生与死是两个世界,互相不影响,里面的逃不出去,外面的进不来。

1. 外边距折叠

发生外边距折叠里面有一个重要条件就是:两个块级盒子属于相同块格式化上下文。如果产生了新的 BFC,自然就不会发生外边距折叠了。

2. 块元素与浮动元素重合

不仅仅是 BFC 内部块盒子会贴着其内容左边区域(视格式化方向,上文有提到),块级盒子内部也是这样。当浮动元素后面跟随块元素时,浮动元素会飘到块元素上面,并挤开块元素内部 inline box。给该块元素使用 BFC,它的左边界就不会延伸到浮动底部了,会贴着浮动的右边界。(不严格的讲,一个 DIV 就会产生一个 block formatting context,所以 DIV 内部布局是上文提到的规则。只不过这个 BFC 不是独立的,会受到外界的影响)

3. 浮动元素引起高度坍塌

浮动元素脱离了正常文档流,会导致父元素高度坍塌,从而导致浮动内容会溢出到父元素外面。这样会覆盖到其他块级盒子上面,或者挤开外部行内元素。使浮动的父元素产生一个 BFC,那么父元素会自动增长到包裹浮动元素,消除外界的相互影响。

总结

除了上面提到几种方案可以使盒子产生新的 BFC,还有很多同学认为 display: flex 也能产生 BFC。这是错误的!!!首先,规范中没有提到。其次,flex 盒子会产生一个新的独立的 flex formatting context ,它可以解决一些 BFC 能解决问题。是因为这个 FFC 是一个独立格式化上下文。FFC 与 BFC 有相同的地方,但更多的是不同。比如:FFC 内部使用的是 flex layout,内部不允许浮动,它的外边距也不会和子元素外边距发生折叠等。这些与 BFC 都是不一样的。

附言

大家如果觉得有什么没有讲清楚的,可以在评论区留言。毕竟我们的目标是让猴子🐒 都能明白 BFC。