理解CSS中的块级格式化上下文

479 查看

块级格式化上下文(Block Formatting Context)是网页CSS视觉渲染的一部分,并用于决定块盒子的布局。在定位体系(Positioning Scheme)中它属于常规流(Normal Flow)。根据W3C所言:

浮动、绝对定位元素(position 为 absolute 或 fixed)、行内块元素 display:inline-block、表格单元格display:table-cell、表格标题 display:table-caption 以及 overflow 属性值不为 visible 的元素(除了该值被传播到视点 viewport 的情况)将创建一个新的块级格式化上下文。

上面的引言差不多总结了一个BFC是如何形成的。但让咱们用另外一种更通俗易懂的方式来重定义它。一个BFC就是一个HTML盒子,它至少满足以下条件之一:

  1. float 的值不为 none
  2. position 的值不为 static 或 relative
  3. display 的值为 table-celltable-captioninline-blockflex 或 inline-flex
  4. overflow 的值不为 visiable

创建一个块级格式化上下文

一个BFC可以显式触发。如果我们想创建之,我们只需给它添加上面提到的任何一个CSS样式。

比如,看下面的HTML:

一个新的BFC可以通过给容器添加任意一个必要的CSS样式来创建,比如overflow: scrolloverflow: hiddendisplay: flexfloat: left,或 display: table。尽管上述条件都可以创建BFC,但也会产生一些其他效果,如:

  1. display: table 可能引发响应性问题
  2. overflow: scroll 可能产生多余的滚动条
  3. float: left 将把元素移至左侧,并被其他元素环绕
  4. overflow: hidden 将裁切溢出元素

所以无论何时,当要创建一个BFC时,我们要基于需求选择最恰当的样式。为了保持一致性,我在本文的所有例子中均使用overflow: hidden

你可以自由选择使用除 overflow: hidden 之外的其他样式。

BFC中盒子的对齐

W3C规范道:

在BFC上下文中,每个盒子的左外侧紧贴包含块的左侧(从右到左的格式里,则为盒子右外侧紧贴包含块右侧),甚至有浮动也是如此(尽管盒子里的行盒子 Line Box 可能由于浮动而变窄),除非盒子创建了一个新的BFC(在这种情况下盒子本身可能由于浮动而变窄)。

简单来说,如上图所示,所以属于BFC的盒子都左对齐(在从左到右的格式下)并且它们的左外侧紧贴包含块的左侧。在最后一个盒子中我们可以看到尽管左侧存在一个浮动元素(棕色),另外一个元素(绿色)仍然紧贴包含块的左侧。该情况的产生原理将在下文关于文字环绕的部分中讨论。

BFC造成的外边距折叠

在常规流中,盒子从包含块的顶部开始一个个地垂直摆放。两个同胞盒子间的垂直举例由两个盒子各自的外边距所决定,但不是二者外边距之和。

为便于理解,我们看个例子。

在上图中,一个红盒子(div)包含着两个同胞绿元素(p),一个BFC已经创建了出来。

相应的CSS是:

理论上两个同胞元素间的外边距应当是二者外边距之和(20px)但实际上却是10px。这就是众所周知的外边距折叠(Collapsing Margins)。如果同胞元素外边距不同,将应用最大的那个。

使用BFC避免外边距折叠

在讨论了上面BFC折叠外边距的情况后,现在说避免折叠可能有点让人摸不着头脑。但我们必须牢记于心的一件事是,相邻块级盒子(同胞)之间的垂直外边距只有在它们处于同一个BFC时才会发生折叠。如果它们分属于不同的BFC,就不会折叠了。所以,通过创建新的BFC我们可以避免外边距折叠。

让我们在早前的例子中添加第三个同胞元素,现在HTML是:

CSS是:

结果和上面一样,即是说,折叠还是会发生并且三个同胞间分隔的垂直距离是10px。这是因为三个 p 标签都从属于同一个BFC。

现在我们修改第三个同胞元素,使之成为一个新的BFC的一部分。现在的HTML变成了:

css: