关于BFC(块级格式化上下文)的探究

BFC探究

目录

  1. BFC的概念
  2. 什么情况下会产生BFC
  3. 一个BFC中的规则
  4. BFC的应用场景
  5. 本文的参考资料

1. BFC的概念

BFC(全称:Block Formatting Context, 直译:块级格式化上下文)。

又是“context”这个单词,谷歌翻译会把它翻译为“上下文、前后关系、景况”,但是个人认为把它翻译为“环境”更好理解一点。

每个context(“环境”)里面总会有一些规则,用来规范在context里面的东西的行为。好比我们在一个学校里上学,“学校”就是一个环境(context),而这个环境里面,我们要遵守这间学校的校规:不能作弊、不能早恋、不能叫外卖、不能不可描述…而这些“校规”,就是这个环境(context)里面的一些“规则”。

那么BFC这个context里面有一些怎样的规则?这些规则是用来规范什么行为的呢?答:BFC里面的规则是一些关于渲染的规则,这些规则规定了在一个块级的盒子模型里面的元素如何渲染(放在什么位置)。

2. 什么情况下会产生BFC

一个元素只要满足下面任意一个条件,就可以产生BFC。

  1. 浮动元素(float属性为非none)
  2. 绝对定位元素(position属性为absolute或fixed)
  3. 块容器(display属性为inline-block, flex, table-cell, table-caption 或者 inline-flex中的其中一个)
  4. overflow属性不为visible的元素

3. 一个BFC中的规则

终于到重头戏了,我们来看看在一个BFC里面有什么规则。

  1. 【盒子的排列】规则:在一个BFC中,每个盒子会从包含块的顶部开始,垂直的一个接一个排列
  2. 【对齐(左对齐)】规则:子元素的左外边框父元素(或者说“包含块”)左边框(即:border-left)对齐。
  3. 【关于浮动元素的渲染】规则:浮动和清除浮动只会应用于同一个BFC内的元素。浮动不会影响其他BFC中的元素,而清除浮动只能清除同一BFC中在它前面的元素的浮动。另外,BFC可以包裹住浮动元素
  4. 【垂直外边距折叠】规则:“垂直外边距折叠”这个现象只会在同一个BFC中的两个相邻块级元素之间发生。
  5. 【隔离】规则:BFC相当于一个隔离的独立容器,容器里面(或者说BFC里面)的元素不会影响到外面的元素
  6. 【包含】规则:一个BFC包含了创建它的元素内部的所有内容。如果一个父元素创建了一个BFC,这个父元素的子元素也创建了一个BFC,那么这个子元素其实也处于父元素所创建的BFC中,也就是说,父元素和子元素都处在同一个BFC中。(这就可以解释为什么在父元素创建BFC,可以解决父元素高度坍塌的问题了)。

4. BFC的应用场景

(为了方便和直观,下面的例子都使用overflow: hidden的方式来产生BFC)

  • 使用BFC来防止外边距折叠

原理:对于在同一BFC里的两个相邻的块元素,把其中一个块元素用一个div去包住它,然后把div的overflow设为hidden使其产生一个新的BFC,这样的话原本那两个相邻的块元素就不在同一个BFC里面了,所以它们的外边距也就不会发生折叠了。

See the Pen BFC实验室2 by aLLeNxD (@AllenMinD) on CodePen.

  • 使用BFC来包含浮动,防止出现父元素“坍塌”现象

对于用一个父元素,如果里面的子元素变成了浮动元素,那么父元素的高度就会发生“坍塌”,这是因为它的子元素是浮动元素(float属性为非none),这就使得子元素产生了一个新的BFC,而由上面的【规则5】可知,一个BFC相当于一个独立的容器,容器里面的元素不会影响到外面的元素,所以子元素并不会影响到父元素的高度,这就是父元素的高度为什么不被浮动的子元素“撑起来”的原因。

而我们的解决方法也是用回BFC来解决:我们只需要给父元素也创建一个BFC,因为由上面的【规则6】可知,一个BFC包含则创建它的元素及其子元素,这样的话,此时的父元素和子元素就算是处在同一个BFC(由父元素所创建的BFC)中了,这就解决了坍塌的问题了。

See the Pen BFC实验室1 by aLLeNxD (@AllenMinD) on CodePen.

  • 使用BFC来防止文字环绕

为p元素创建BFC,由于浮动只会影响同一BFC里的其他元素,而现在p元素和那个浮动的元素已经不在同一BFC了,所以p元素里的文字不会环绕。

See the Pen BFC实验室3 by aLLeNxD (@AllenMinD) on CodePen.

  • 在多列布局中使用BFC,防止最后一列被“挤到”下一行去

(这个例子不好理解,而且可以使用flex布局来代替解决,所以这里就不做深究了。)

See the Pen BFC实验室4 by aLLeNxD (@AllenMinD) on CodePen.

5. 本文的参考资料

  1. MDN文档
  2. 《Understanding Block Formatting Contexts in CSS》中文版
  3. 《Understanding Block Formatting Contexts in CSS》英文原版
  4. W3C规范

    9.4.1 Block formatting contexts
    Floats, absolutely positioned elements, block containers (such as inline-blocks, table-cells, and table-captions) that are not block boxes, and block boxes with ‘overflow’ other than ‘visible’ (except when that value has been propagated to the viewport) establish new block formatting contexts for their contents.

    In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the ‘margin’ properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.

    In a block formatting context, each box’s left outer edge touches the left edge of the containing block (for right-to-left formatting, right edges touch). This is true even in the presence of floats (although a box’s line boxes may shrink due to the floats), unless the box establishes a new block formatting context (in which case the box itself may become narrower due to the floats).

    For information about page breaks in paged media, please consult the section on allowed page breaks.

  5. 以为网友的总结