CSS BFC(块级格式化上下文)
BFC 的定义、触发条件、布局效果,以及 margin 合并问题。
#frontend
#css
#concept
#growing
[!info] related notes
- 所属 MOC: CSS MOC
- 相关概念: css-flexbox, css-grid, 回流和重绘有什么区别
CSS BFC(块级格式化上下文)
定义
BFC(Block Formatting Context,块级格式化上下文)是块级布局的一种格式化上下文,规定块盒与浮动如何参与布局,以及外边距何时可以合并。
它不是完全隔离的渲染区域:内部内容仍可能改变容器尺寸,并影响外部布局。它提供的是特定的浮动与外边距边界。
触发条件
常见的 BFC 建立条件:
html根元素(本身就是一个 BFC)float不为none(left、right)position为absolute或fixed- 块盒的 overflow 计算值不是
visible或clip,例如hidden、auto、scroll;overflow: clip单独使用不会创建 BFC display为inline-block、table-cell、table-captiondisplay: flow-root(最语义化的触发方式)contain为layout、content、paint
Flex、Grid 容器建立的是各自的格式化上下文,不应直接称为 BFC;它们的子项布局与 margin 规则需要分别理解。
BFC 的布局效果
1. 包含浮动(清除浮动)
建立 BFC 的容器在计算自动高度时,会纳入属于该 BFC 的浮动后代。这不意味着任意固定高度或过宽内容都不会溢出。
<div class="parent">
<div class="float-child">浮动元素</div>
</div>
<!-- parent 的高度塌陷,因为浮动子元素脱离了文档流 -->
.float-child { float: left; }
/* 创建 BFC 来包含浮动 */
.parent {
display: flow-root; /* 触发 BFC */
}
这比用 clearfix 或 overflow: hidden 更语义化。
2. 阻止 margin 合并(margin collapse)
普通块级布局中,相邻垂直 margin 可能合并;两个正 margin 合并时取较大值,涉及负值时不能套这个规则。BFC 可阻止容器与内部子元素的 margin 合并,但不会消除同一 BFC 内相邻兄弟之间的合并。
<div class="a">上</div>
<div class="b">下</div>
.a { margin-bottom: 30px; }
.b { margin-top: 20px; }
/* 实际间距是 30px,不是 50px —— margin 合并了 */
把其中一个元素包裹在 BFC 容器中,就可以阻止合并:
<div class="wrapper-bfc">
<div class="b">下</div>
</div>
.wrapper-bfc {
display: flow-root; /* 创建 BFC */
}
3. 阻止元素被浮动元素覆盖
普通流中建立 BFC 的块盒,其 border box 不与同一外部 BFC 中的浮动 margin box 重叠;空间不足时可能下移。
.sidebar {
float: left;
width: 200px;
}
.main {
overflow: hidden; /* 创建 BFC,不与 .sidebar 重叠 */
}
margin 合并的三种情况
- 相邻兄弟元素:上一个的
margin-bottom和下一个的margin-top合并 - 父子元素:没有对应边框、内边距、行盒等分隔且满足正常流条件时,父元素与第一个正常流子元素的顶部 margin 可能合并;底部合并还有高度约束
- 空块元素:自身的
margin-top和margin-bottom合并
阻止父子 margin 合并的常见方式:
- 给父元素创建 BFC(
display: flow-root) - 给父元素加
border或padding - 给父元素加
overflow: hidden(也创建 BFC)
实际应用场景
清除浮动
/* 最佳实践:使用 display: flow-root */
.clearfix-container {
display: flow-root;
}
两栏自适应布局
.layout {
display: flow-root;
}
.sidebar {
float: left;
width: 200px;
}
.content {
overflow: hidden; /* BFC,自适应剩余宽度 */
}
防止 margin 穿透
.card-wrapper {
display: flow-root; /* 阻止内部 margin 合并到外部 */
}
边界
overflow: hidden可以创建 BFC,但会裁剪溢出内容,不总是合适display: flow-root可以建立 BFC 而不附带 overflow 裁剪,但它仍会改变浮动包含和 margin 行为- BFC 不是 CSS 属性,而是浏览器的渲染行为,不能直接”设置” BFC
- Flexbox 和 Grid 容器也会创建类似 BFC 的格式化上下文(分别是 FFC 和 GFC)
- 浮动元素本身也创建 BFC
一句话记忆法
BFC 提供块级布局的浮动与 margin 边界;需要建立这个边界且不想附带裁剪时,可用 display: flow-root。