BFC 的形成和作用

开发/前端 · 阅读 1733 · 点赞 0

BFC 是什么

BFC 全称为 block formatting context,中文为“块级格式化上下文”。它是一个只有块级盒子参与的独立块级渲染区域,它规定了内部的块级盒子如何布局,且与区域外部无关。

BFC 有什么用

  • 修复浮动元素造成的高度塌陷问题。
  • 避免非期望的外边距折叠。
  • 实现灵活健壮的自适应布局。

触发 BFC 的常见条件

  • <html> 根元素。
  • float 的值不为 none。
  • position 的值不为 relative 或 static。
  • overflow 的值不为 visible 或 clip(除了根元素)。
  • display 的值为 table-cell,table-caption,或 inline-block 中的任意一个。
  • display 的值为 flow-root,或 display 值为 flow-root list-item。
  • flex items,即 display 的值为 flex 或 inline-flex 的元素的直接子元素(该子元素 display 不为 flex,grid,或 table)。
  • grid items,即 display 的值为 grid 或 inline-grid 的元素的直接子元素(该子元素 display 不为 flex,grid,或 table)。
  • contain 的值为 layout,content,paint,或 strict 中的任意一个。
  • column-span 设置为 all 的元素。

提示display: flow-rootcontain: layout 等是无副作用的,可在不影响已有布局的情况下触发 BFC。

知识点深入

1. 前置知识点

盒模型(box model)

盒模型描述了一个由元素生成的矩形盒子,视觉格式化模型决定这些盒子的大小、位置以及属性(例如颜色、背景、边框尺寸等等)。

盒子的具体构成如下图所示:

Box model

术语解析

由于视觉格式化模型描述中,有许多相近的术语,在此先行列出解释。

  • box(盒子):一个抽象概念,在画布上占据一块空间,通常由元素(element)生成。一个元素可能生成多个盒子(如伪元素、list-item 元素)。
  • principal box(主要盒子):元素生成的多个盒子中,用来包含它的后代盒子和它生成的内容的盒子,也是参与任何定位方案的盒子。
  • block-level box(块级盒子):参与 BFC 布局的盒子,通常由块级元素生成。
  • block container box(块容器):在 CSS2.2 中,除了 table box 或替换元素的主要盒子,一个块级盒子也是块容器,但不是所有的块容器都是块级盒子(如非替换内联块盒子)。块容器主要侧重于其子元素的定位、布局。
  • block box(块盒子):如果一个块级盒子同时也是块容器,则可以称作块盒子。
  • block(块):当没有歧义时,作为 block box, block-level box 或 block container box 的简写。

(注:盒子有“块盒子”和“块级盒子”,元素只有“块级元素”,而没有“块元素”)

2. 视觉格式化模型(visual formatting model)

视觉格式化模型描述了用户代理(如浏览器)在可视化媒体(如显示器)上处理文档树(document tree)的过程。下面各小节是视觉格式化模型中与 BFC 强相关的描述:

2.1 包含块(containing block)

大部分情况下,包含块是一个由元素最近的祖先块容器的内容区域(content area)确定的矩形区域,包含块本身不是盒子,是一个矩形区域。元素的大小,位置,及偏移等布局信息根据包含块的尺寸进行计算。

2.2 正常流(normal flow)

正常流是浏览器的默认布局方式。在正常流中的盒子,属于 BFC,IFC,或其他格式化上下文之一。

2.3 格式化上下文(formatting context)

格式化上下文是一系列相关盒子进行布局的环境。不同的格式化上下文有不同的布局规则。目前常见的格式化上下文有以下这些:

  • 块级格式化上下文(BFC,block formatting context)。
  • 内联格式化上下文(IFC,inline formatting context)。
  • 弹性格式化上下文(FFC,flex formatting context),在 CSS3 中定义。
  • 栅格格式化上下文(GFC,grid formatting context),在 CSS3 中定义。

2.4 独立格式化上下文(independent formatting context)

一个盒子要么建立一个新的独立格式化上下文,要么延续其包含块的格式化上下文。除了特殊说明,建立新的格式化上下文就是在建立一个独立格式化上下文。

当一个盒子建立一个独立格式化上下文时,它创建了一个新的独立布局环境。除了通过改变盒子本身的大小,盒子内部的后代不会影响格式化上下文外部的规则和内容,反之亦然。

2.5 块级格式化上下文规范及解析

根据 W3C CSS2.1 视觉格式化模型一章的定义,BFC 相关规范描述如下:

  1. 浮动元素,绝对定位元素,不是块级盒子的块级容器(如 inline-block,table-cells,table-captions)以及 overflow 值不为 visible 的块级盒子,都会为他们的内容创建 BFC(注:触发 BFC 的条件)。
  2. 在 BFC 中,盒子从包含块的顶部开始,在垂直方向上一个接一个的排列。相邻盒子之间的垂直间隙由它们的 margin 值决定。在同一个 BFC 中,相邻块级盒子的垂直外边距会合并(注:参与 BFC 布局的都是块级元素)。
  3. 在 BFC 中,每一个盒子的左外边缘(margin-left)会触碰到包含块的左边缘。即使是存在浮动元素也是如此,除非该盒子建立了一个新的 BFC。

结合规范第三点与独立格式化上下文的知识,我们可以有以下推论:

  1. BFC 内外互不影响。
    1. BFC 包含内部的浮动(解决内部浮动元素导致的高度塌陷)。
    2. BFC 排斥外部的浮动(触发 BFC 的元素不会和外部的浮动元素重叠)。
    3. 外边距折叠的计算不能跨越 BFC 的边界。
  2. 各自创建了 BFC 的兄弟元素互不影响(注:在水平方向上多个浮动元素加一个或零个触发 BFC 的元素可以形成多列布局)。

通过 BFC 可以实现灵活健壮的自适应布局,在一行中达到类似 flexbox 的效果,示例如下:

两栏自适应布局

two-col

多列自适应布局

multi-col