什么是 BFC?
BFC(Block formatting context),直译为"块级格式化上下文"。 它是一个独立的渲染区域,只有 Block-level box(块级盒子)参与, 它规定了内部的 Block-level Box 如何布局,并且与这个区域外部毫不相干。 它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系和相互作用。
布局规则
- 内部的 Box 会在垂直方向,一个接一个放置
- Box 垂直方向的距离由 Margin 决定。属于同一个 BFC 的两个相邻的 Box 的 margin 会发生重叠。
- 每个盒子(块盒与行盒)的 margin box 的左边,与包含块 border box 的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
- BFC 的区域不会与 float box 重叠。
- BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
- 计算 BFC 的高度时,浮动元素也参与计算。
建立 BFC
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)
- body 根元素
特性及应用
同一个 BFC 下外边距会发生折叠
.div1 {
width: 100px;
height: 20px;
margin: 10px;
border: 1px solid #000;
}
因为两个 div 元素都处于同一个 BFC 容器下 (这里指 body 元素) 所以第一个 div 的下边距和第二个 div 的上边距发生了重叠。两个盒子之间的距离并没有 20px,只有 10px 。 首先这不是 CSS 的 bug,我们可以理解为一种规范
.container {
overflow: hidden;
}
.div1{
width: 100px;
height: 20px;
margin: 10px;
border: 1px solid #000;
overflow: hidden;
}
<div class="container"><div class="div1"></div></div>
<div class="container"><div class="div1"></div></div>
如果想要避免外边距的重叠,可以将其放在不同的 BFC 容器中。
BFC 可以包含浮动的元素(清除浮动)
我们都知道,浮动的元素会脱离普通文档流,来看下下面一个例子
<div style="border: 1px solid #000;">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
由于容器内元素浮动,脱离了文档流,所以容器只剩下 2px 的边距高度。如果使触发容器的 BFC,那么容器将会包裹着浮动元素。
<div style="border: 1px solid #000;overflow: hidden">
<div style="width: 100px;height: 100px;background: #eee;float: left;"></div>
</div>
效果如图:
BFC 可以阻止元素被浮动元素覆盖
先来看一个文字环绕效果:
<div style="height: 100px;width: 100px;float: left;background: lightblue">我是一个左浮动的元素</div>
<div style="width: 200px; height: 200px;background: #eee">我是一个没有设置浮动,
也没有触发 BFC 元素, width: 200px; height:200px; background: #eee;</div>
这时候其实第二个元素有部分被浮动元素所覆盖,(但是文本信息不会被浮动元素所覆盖) 如果想避免元素被覆盖,可触第二个元素的 BFC 特性(BFC 的区域不会与 float box 重叠),在第二个元素中加入 overflow: hidden,就会变成: 这个方法可以用来实现两列自适应布局,效果不错,这时候左边的宽度固定,右边的内容自适应宽度(去掉上面右边内容的宽度)。
总结
它可以解决:
边距重叠问题(下边距重叠/上边距塌陷)
高度塌陷(清除浮动,当我们不给父节点设置高度,子节点设置浮动的时候,会发生高度塌陷)(计算 BFC 高度时浮动元素也参于计算)
实现多栏布局(左侧 float:left 固定宽,右侧创建 BFC)