CSS

对BFC块级格式化上下文的理解

学习理解BFC块级格式化上下文

Yixuan Lang
2021-10-01
4 min

# 对 BFC 块级格式化上下文的理解

CSS_BFC

BFCCSS中比较重要的一个概念,它不但能解决很多问题,还可以解释 CSS 中一些诡异的地方,所以搞懂 BFC 对于学习 CSS 来说是很有必要的。

# 1. 什么是 BFC?

BFC 的全称是Block Formatting Context即块级格式化上下文,是 W3C CSS2.1 规范中的一个概念。它是==页面中的一块渲染区域==,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。

具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。

🌈 通俗一点来讲,可以把 BFC 理解为一个封闭的大箱子,箱子内部的元素无论如何翻江倒海,都不会影响到外部。

# 2. BFC 的特点

我们从 BFC 的原理开始看起,简单来说其实也就是 BFC 的渲染规则,主要有下面几点:

  • 垂直⽅向上,⾃上⽽下排列,和⽂档流的排列⽅式⼀致。
  • 在 BFC 中上下相邻的两个容器的 margin 会重叠
  • 计算 BFC 的⾼度时,需要计算浮动元素的⾼度
  • BFC 区域不会与浮动的容器发⽣重叠
  • BFC 是独⽴的容器,容器内部元素不会影响外部元素
  • 每个元素的左 margin 值和容器的左 border 相接触

# 3. 如何触发 BFC?

既然 BFC 是一块渲染区域,那这块渲染区域到底在哪,它又是有多大,而这些则由生成 BFC 的元素决定(即哪些元素会生成 BFC),我们在这里也只列举一些比较常见的,完整的列表可以参考 MDN - 块格式化上下文

  • float 属性不为 none,意思是,只要设置了浮动,当前元素就创建了 BFC

  • overflow 的值不为 visible,可以让属性是 hiddenauto

  • positionabsolutefixed

  • display 值为:inline-blocktable-celltable-captionflex等;

    • 关于 display:table,之所以可以生成 BFC,主要原因在于 table 会默认生成一个匿名的 table-cell
    • 正是这个匿名的 table-cell 生成了 BFC
  • 弹性元素(displayflexinline-flex 元素的直接子元素)

  • 网格元素(displaygridinline-grid 元素的直接子元素)

# 4. BFC 有何作用?

对 BFC 的特性有了一定的了解后,可以利用这些规则,来解决我们平常遇到过的一些问题

# 1. 解决 margin 的重叠问题

CSS 的规范规定,相邻元素的外边距会重叠。BFC 可以解决该问题,由于 BFC 是⼀个独⽴的区域,内部的元素和外部的元素互不影响,将两个元素变为两个 BFC,就解决了 margin 重叠的问题。

👉 没有解决 margin 重叠问题的案例:

<style>
p {
  color: #f55;
  background: #fcc;
  width: 200px;
  line-height: 100px;
  text-align:center;
  margin: 100px;
}
</style>

<body>
  <p>Haha</p>
  <p>Hehe</p>
</body>
image-20220308101744491

👉 使用 BFC 解决 margin 重叠的问题:据规则可知,属于同一个 BFC 的两个相邻 boxmargin 会发生重叠,解决办法也很简单,我们可以给其中任意一个元素包裹一层容器,并触发该容器生成 BFC,那么此时的两个子元素就不属于同一个 BFC,所以就不会发生 margin 重叠的现象了

<style>
.wrap {
  overflow: hidden;
}

p {
  color: #f55;
  background: #fcc;
  width: 200px;
  line-height: 100px;
  text-align:center;
  margin: 100px;
}
</style>

<body>
  <p>Haha</p>
  <div class="wrap">
    <p>Hehe</p>
  </div>
</body>
image-20220308102202461

# 2. 解决⾼度塌陷的问题

在对⼦元素设置浮动后,⽗元素会发⽣⾼度塌陷,也就是⽗元素的⾼度变为 0。解决这个问题,只需要把⽗元素变成⼀个 BFC。常⽤的办法是给⽗元素设置overflow:hidden

👉 没有解决高度坍塌问题案例:

<style>
.par {
  border: 5px solid #fcc;
  width: 300px;
}

.child {
  border: 5px solid #f66;
  width:100px;
  height: 100px;
  float: left;
}
</style>

<body>
  <div class="par">
    <div class="child"></div>
    <div class="child"></div>
  </div>
</body>

高度坍塌问题1

👉 使用 BFC 解决高度坍塌问题:发生这种情况的原因是因为内部的 child 元素使用了 float,使其脱离了文档流,故父元素的高度自然就没有了,解决办法有很多,原理只需要将父元素触发为 BFC 即可

.par {
  overflow: hidden;
}

高度坍塌问题2

# 3. 创建⾃适应两栏布局

可以⽤来创建⾃适应两栏布局:左边的宽度固定,右边的宽度⾃适应。

<style>
body {
  width: 300px;
  position: relative;
}

.aside {
  width: 100px;
  height: 150px;
  float: left;
  background: #f66;
}

.main {
  height: 200px;
  background: #fcc;
}
</style>

<body>
  <div class="aside"></div>
  <div class="main"></div>
</body>

自适应两栏布局1

👉 使用 BFC 创建自适应两栏布局:根据规则可知,虽然存在浮动的元素 aslide,但 main 的左边依然会与包含块的左边相接触,这是因为 BFC 不会与 float box 重叠,所以我们可以将 main 生成为 BFC 即可

.main {
  overflow: hidden;
}

自适应两栏布局2

# 参考文章

CSS:BFC 块格式化上下文

彻底搞懂 CSS 里的 BFC | 8 月更文挑战

理解 CSS 布局和 BFC

10 分钟理解 BFC 原理