- Published on
BFC(Block-Formatting-Context)-块级格式化上下文
- Authors

- Name
- Li WenKang
- https://x.com/liwenkang_space
接下来将会更新一系列文章,每篇文章将会聚焦一个概念,从以下四个角度回答问题:是什么?如何创建(使用)?解决了什么问题?最佳实践有哪些?这是系列的第一篇,关于 BFC。
BFC 是什么?
BFC 全称是(Block-Formatting-Context)块级格式化上下文,BFC内部的块级盒子会在垂直方向上一个接一个地放置,属于同一个BFC的两个相邻Box的垂直margin会发生重叠。BFC就是页面上的一个隔离的独立容器,容器内部的子元素不会影响外层样式,外层样式也无法影响容器内层样式,BFC的区域不会与浮动元素(float box)发生重叠。
如何创建 BFC?
<html>标签本身就是一个 BFC- 设置 overflow:hidden/auto/scroll
- 设置 display:flex/grid/inline-block/flow-root/inline-flex/inline-grid/table-cell
- 设置 position:absolute/fixed
- 设置 float 不是 none,即 left/right
BFC 解决了什么问题?
- 全部子元素都设置 float 后,造成的父元素高度塌陷。BFC可以包含浮动元素,使得计算BFC的高度时,浮动元素的高度也参与计算,从而避免了高度塌陷。
<!-- 1. 子元素全部浮动之后,父元素高度塌陷 -->
<html>
<body>
<div class="parent">
<div class="child"></div>
</div>
</body>
</html>
<style>
.parent {
width: 300px;
background-color: red;
display: flow-root; /* 解决高度塌陷问题 */
}
.child {
width: 100px;
height: 100px;
background-color: blue;
float: right;
}
</style>
- 在同一个 BFC 中,相邻块级元素的 margin 合并问题
<!-- 2. 在一个 BFC 中,上下相邻的块级元素 margin 合并 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.box {
background-color: #f0f3f9;
}
.box p {
outline: solid deepskyblue;
margin: 2em;
}
.flow-root {
display: flow-root;
}
</style>
</head>
<body>
<!--
在正常的预期中,子元素的 margin-top 应该在其父元素的“内部”产生间距。
但当穿透发生时,这个外边距就像穿过了父元素的“屋顶”,直接作用在了父元素的外部,导致父元素整体与其上方元素的距离被改变。
-->
<div class="box">
<p>margin: 2em;</p>
</div>
<!--
上面的 .box容器:因为没有采取任何隔离措施,其内部 <p>标签的 margin-top穿透了容器,直接变成了容器本身的 margin-top。
这导致容器的背景色(浅灰色)是从内容区域开始绘制的,并没有覆盖到被“穿透”的那部分外边距区域。
-->
<!--
下面的 .flow-root容器:因为设置了 display: flow-root,它创建了一个块级格式化上下文(BFC)。
BFC就像一个独立的布局容器,它内部元素的布局(包括外边距)不会影响到外部。
所以 <p>标签的 margin被“困”在了这个独立的布局环境内,在容器内部产生了预期的间距,同时容器的背景色也完整地覆盖了这个区域。
-->
<div class="box flow-root">
<p>margin: 2em;</p>
</div>
</body>
</html>
- 当左侧 float+固定宽度,右侧自适应宽度布局时,会出现悬浮元素遮盖问题
<!-- 3. 左侧固定宽度+ float,右侧自适应宽度时,浮动元素遮蔽问题 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
.container {
width: 100%;
height: 100vh;
background-color: green;
}
.left-box {
width: 200px;
height: 100%;
float: left;
background-color: red;
margin-right: 20px;
}
.right-box {
background-color: blue;
padding: 10px;
/* 这行代码将把 右侧内容 包裹在一个新的 BFC 中,从而避免浮动元素遮蔽问题 */
display: flow-root;
}
</style>
</head>
<body>
<div class="container">
<div class="left-box">
<div class="left-box-item">左侧内容</div>
</div>
<div class="right-box">
<div class="right-box-item">右侧内容</div>
</div>
</div>
</body>
</html>
- 文本环绕问题
<!-- 4. 当非BFC容器内的文本遇到浮动元素时,会发生环绕现象。通过BFC可强制文本换行 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
p {
display: flow-root;
}
</style>
</head>
<body>
<div style="float: left; width: 100px; height: 100px;"></div>
<p>
这段文本会环绕浮动元素...这段文本会环绕浮动元素...这段文本会环绕浮动元素...这段文本会环绕浮动元素...
</p>
</body>
</html>
BFC 最佳实践有哪些?
- 优先使用 flex/grid 等现代布局方法,如果仅为了实现 BFC,可以优先考虑 display:flow-root,避免 overflow: hidden 造成的裁切问题
- 在处理 margin 合并问题时,无需让相邻的元素都构建 BFC,只需要给其中一个加上就行
扩展内容
- BFC (块级格式化上下文)、FFC (弹性格式化上下文)、GFC (网格布局格式化上下文)、IFC (行内格式化上下文)
- 处理历史布局问题:对于需要清除浮动、防止外边距合并或处理文字环绕等经典问题,BFC 依然是直接有效的解决方案。在现代布局中,它更像一个精细的调整工具
- 安排组件内部布局:对于组件内部的一维线性布局,比如导航栏、工具条、卡片列表等,FFC(Flexbox布局)通常更简单灵活。它在内容动态分布和对齐方面表现出色
- 构建整体页面结构:当需要设计复杂的二维布局(如整个页面的头部、主体、侧边栏和底部区域),并且需要同时精确控制行和列时,应优先选择 GFC(Grid布局)。它提供了最强大的布局能力
- 理解行内元素排版:IFC 的概念虽然不常直接使用,但理解它有助于更好地控制文本和行内元素的垂直对齐、行高等细节