# 对 BFC 块级格式化上下文的理解
BFC
是CSS
中比较重要的一个概念,它不但能解决很多问题,还可以解释 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
,可以让属性是hidden
、auto
position
为absolute
或fixed
display
值为:inline-block
、table-cell
、table-caption
、flex
等;- 关于
display:table
,之所以可以生成BFC
,主要原因在于table
会默认生成一个匿名的table-cell
- 正是这个匿名的
table-cell
生成了BFC
- 关于
弹性元素(
display
为flex
或inline-flex
元素的直接子元素)网格元素(
display
为grid
或inline-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>

👉 使用 BFC 解决 margin 重叠的问题:据规则可知,属于同一个 BFC
的两个相邻 box
的 margin
会发生重叠,解决办法也很简单,我们可以给其中任意一个元素包裹一层容器,并触发该容器生成 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>

# 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>
👉 使用 BFC 解决高度坍塌问题:发生这种情况的原因是因为内部的 child
元素使用了 float
,使其脱离了文档流,故父元素的高度自然就没有了,解决办法有很多,原理只需要将父元素触发为 BFC
即可
.par {
overflow: hidden;
}
# 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>
👉 使用 BFC 创建自适应两栏布局:根据规则可知,虽然存在浮动的元素 aslide
,但 main
的左边依然会与包含块的左边相接触,这是因为 BFC
不会与 float box
重叠,所以我们可以将 main
生成为 BFC
即可
.main {
overflow: hidden;
}