导入

在我们前端开发过程中,经常会遇到例如浮动、样式重叠、高度塌陷之类的等问题,这些都与接下来要说的BFC有着密切的关系。

什么是BFC?

在W3C CSS2.1里面提出了 Formatting context (格式化上下文)的概念,所谓格式化上下文,简单来说就是页面中一块独立的渲染区域,这个区域它拥有自己的渲染规则,并且能决定其子元素如何定位,以及和其他元素的关系和相互作用。
而我们今天说到的块级格式上下文 (Block formatting context,简称BFC) 就是 Formatting context 的中最常见的一种。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域的外部毫不相干。 Block-level box,是display属性为 block, list-item, table 的元素,会生成 Block-level box,并且参与 Block formatting context。

BFC的布局规则

  • Box 会在垂直方向,按照从上到下的方式逐个排列;
  • Box 垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box 的 margin 会发生重叠
  • 每个元素的 margin box的左边, 与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此;
  • BFC 的区域不会与 float box 重叠;
  • 计算 BFC 的高度时,浮动元素的高度也参与计算;
  • BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。

BFC的触发条件

  • 根元素(html)
  • 浮动元素(float 值不为 none)
  • 绝对定位元素(position 值为 absolute 或 fixed)
  • 行内块元素(display 值为 inline-block)
  • 表格单元格(display 值为 table-cell,HTML 表格单元格默认值)
  • 表格标题(display 值为 table-caption,HTML 表格标题默认值)
  • 匿名表格单元格元素(display 值为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是 HTML table、tr、tbody、thead、tfoot 的默认值)或 inline-table)
  • overflow 值不为 visible、clip 的块元素
  • display 值为 flow-root 的元素
  • contain 值为 layout、content 或 paint 的元素
  • 弹性元素(display 值为 flex 或 inline-flex 元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器
  • 网格元素(display 值为 grid 或 inline-grid 元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器
  • 多列容器(column-count 或 column-width (en-US) 值不为 auto,包括column-count 为 1)
  • column-span 值为 all 的元素始终会创建一个新的 BFC,即使该元素没有包裹在一个多列容器中 (规范变更, Chrome bug)

应用举例

例1

  • 验证规则:内部的Box会在垂直方向,按照从上到下的方式逐个排列。
  • 原因:因为 body 元素本默认 display 属性值为 “block”,使得 body 内部成为一个 Block-level Box。

前端架构需求规格说明书_前端

例2

  • 验证规则:Box垂直方向的距离由 margin 决定。属于同一个 BFC 的两个相邻 Box的 margin 会发生重叠,box1 的 margin-bottom 为 100px,box2 的 margin-top 为 100px,理想状态两个 box 的垂直间距应该为 200px,但是因为发生重叠现在只有 100px。

前端架构需求规格说明书_HTML_02

  • 解决方法:在 box2 上包裹一层容器,并触发该容器生成一个BFC。那么两个 box 便不属于同一个BFC,就不会发生 margin 重叠了。

前端架构需求规格说明书_前端_03

例3

  • 验证规则:每个元素的 margin box的左边, 与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反),即使存在浮动也是如此。
  • 简单来说:一个 bfc 中,如果存在一个浮动的盒子,而其他盒子并没有形成新的 bfc,那么所有的子盒子都应该触碰到其包含块的左边缘。下列例子中,父盒子 parent 使用 overflow: hidden 形成 bfc,其中子盒子 son1 浮动,son2 不浮动。那么浮动盒子 son1 就会盖住不浮动盒子 son2,且两个盒子都会触碰到 bfc 的 content-box。

前端架构需求规格说明书_前端_04

例4

  • 验证规则:BFC 的区域不会与 float box 重叠。
  • box1 设置 float: left; 成为浮动盒子,box2 设置 overflow: hidden; 后成为 BFC,图中可以看到两个盒子是不会重叠的。
  • 前端架构需求规格说明书_html_05


  • 前端架构需求规格说明书_HTML_06

例5

  • 验证规则:BFC 的区域不会与 float box 重叠。
  • 未形成 BFC 时,parent 的高度为 0,并没有计算浮动元素的高度。

前端架构需求规格说明书_html_07

  • parent 成为 BFC 后,其高度加上了浮动元素 son 的高度,从 0 变为 200px。

前端架构需求规格说明书_HTML_08


感谢您的阅览,欢迎批评指正!!!