CSS BFC(块级格式化上下文)
BFC 的定义、触发条件、布局效果,以及 margin 合并问题。
#tech / dev / frontend
#resource / css
#type / concept
#status / growing
[!info] related notes
- 所属 MOC: CSS MOC
- 相关概念: css-flexbox, css-grid, reflow-vs-repaint-interview-question
CSS BFC(块级格式化上下文)
定义
BFC(Block Formatting Context,块级格式化上下文)是页面中一块独立的渲染区域。BFC 内部的布局不会影响外部,外部也不会影响内部。
可以把它理解成一个”隔离容器”:内部的浮动、margin、布局计算都被限制在这个区域内。
触发条件
以下任意一条都会创建一个新的 BFC:
html根元素(本身就是一个 BFC)float不为none(left、right)position为absolute或fixedoverflow不为visible(hidden、auto、scroll、overlay)display为inline-block、table-cell、table-caption、flex、grid、inline-flex、inline-griddisplay: flow-root(最语义化的触发方式)contain为layout、content、paint
BFC 的布局效果
1. 包含浮动(清除浮动)
BFC 会包含其内部的浮动子元素,不会让浮动元素”溢出”。
<div class="parent">
<div class="float-child">浮动元素</div>
</div>
<!-- parent 的高度塌陷,因为浮动子元素脱离了文档流 -->
/* 创建 BFC 来包含浮动 */
.parent {
display: flow-root; /* 触发 BFC */
}
这比用 clearfix 或 overflow: hidden 更语义化。
2. 阻止 margin 合并(margin collapse)
相邻的块级元素的垂直 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 区域不会与浮动元素重叠。
.sidebar {
float: left;
width: 200px;
}
.main {
overflow: hidden; /* 创建 BFC,不与 .sidebar 重叠 */
}
margin 合并的三种情况
- 相邻兄弟元素:上一个的
margin-bottom和下一个的margin-top合并 - 父子元素:父元素没有
border、padding、inline content或 BFC 时,子元素的margin-top会和父元素合并 - 空块元素:自身的
margin-top和margin-bottom合并
阻止方式:
- 给父元素创建 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 触发方式,没有副作用- BFC 不是 CSS 属性,而是浏览器的渲染行为,不能直接”设置” BFC
- Flexbox 和 Grid 容器也会创建类似 BFC 的格式化上下文(分别是 FFC 和 GFC)
- 浮动元素本身也创建 BFC
一句话记忆法
BFC 是独立渲染区域:包含浮动、阻止 margin 合并、不与浮动重叠。最干净的触发方式是 display: flow-root。