CSS 中的 块级格式上下文(Block Format Context)

900 阅读4分钟

格式化上下文是根据特定规则布置后代盒子的区域。页面上的所有内容都是格式化上下文的一部分。根元素建立了一个块格式化上下文,其中子元素根据块和内联布局规则进行布局。标准流中的盒子属于格式化上下文,可以是块或内联的,但不能同时是两者。块级盒子属于块格式化上下文。内联级盒子属于内联格式化上下文

一、块级格式上下文(Block Format Context,BFC)

块格式化上下文(Block Formatting Context,BFC)  是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

W3C 中介绍了哪些情况下会创建块级格式上下文:

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.

即:

  • 根元素<HTML>
  • 浮动元素,即:float 值不为 none
  • 绝对定位元素,即:position 值为 absolute 或 fixed
  • 行内块元素,即 display 值为 inline-block
  • 表格单元格、表格标题、匿名表格单元格元素,即:display值为 table-celltable-caption、 tabletable-row、 table-row-grouptable-header-grouptable-footer-group或 inline-table
  • 弹性元素,即:display 值为 flex 或 inline-flex 元素的直接子元素,且它们本身既不是弹性网格也不是表格容器。
  • 网格元素,即:display值为 grid 或 inline-grid 元素的直接子元素,且它们本身既不是弹性网格也不是表格容器。
  • display 值为 flow-root 的元素
  • overflow 值不为 visibleclip 的块元素

当我们给容器添加上述任意一个 CSS 属性,都会显示触发块级格式上下文,即创建一个新的块级格式上下文。

二、BFC 的作用

2.1 BFC 解决 margin 合并问题

(1)margin 合并

margin 合并是指块级元素的上外边距与下外边距有时会合并为单个外边距,即我们常说的外边距塌陷

通常有以下几种情况:

  • 相邻盒子下外边距与上外边距合并

截图.png

  • 当一个元素包含另一个元素时,且外层元素未设置 border 和 padding时, 它们的上和/或下外边距也会发生合并

截图.png

  • 假设有一个空元素,它有外边距,但是没有边框或填充。在这种情况下,上外边距与下外边距就碰到了一起,它们会发生合并

截图.png

如果这个外边距遇到另一个元素的外边距,它还会发生合并:

截图.png

(2)解决 margin 合并

首先我们看 W3C 中的一段介绍:

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.

即:在块格式化上下文中,框中的块级元素从顶部开始一个接一个地垂直排列。两个同级框之间的垂直距离由“margin”属性确定。块格式化上下文中相邻块级框之间的垂直边距折叠

所以说,可以通过创建新的块级格式上下文,使得盒子不属于同一个块级格式上下文,就不会发生外边距塌陷了。

举个例子:

<div class="blue"></div>
<div class="red"></div>
.blue {
    height: 50px;
    margin: 20px 0;
    background: blue;
}

.red {
    height: 50px;
    margin: 30px 0;
    background: red;
}

image.png

当我们做如下修改后,就不会发生外边距塌陷:

<div class="blue"></div>
<div class="outer">
    <div class="red"></div>
</div>
.outer {
    overflow: hidden;
}

image.png

这是因为给 outer 设置了 overflow: hidden;,创建了一个新的块级格式上下文,所以redblue 不属于同一块级格式上下文,所以不会 margin 合并。

2.2 使用块格式化上下文来包含浮动

首先还是看 W3C 中的一段介绍

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).

很多时候我们会遇到容器有浮动元素的情况。在这种情况下,容器元素没有高度,并且它的浮动子元素超出了页面的正常流程。我们通常使用清除浮动来解决这个问题。但我们也可以通过定义块格式化上下文来实现这一点。

<div class="container">
    <div>Sibling</div>
    <div>Sibling</div>
</div>
.container {
  background-color: green;
}

.container div {
  float: left;
  background-color: lightgreen;
  margin: 10px;
}

image.png

如果做如下修改:

.container {
  overflow: hidden; /* creates block formatting context */
  background-color: green;
}

.container div {
  float: left;
  background-color: lightgreen;
  margin: 10px;
}

image.png

以上就是个人对于块级格式化上下文一些简单的学习。

参考:
Block Formatting Contexts in CSS
块格式化上下文
CSS: What is Block Formatting Context (BFC)?