一、什么是 BFC?

通俗来讲,BFC(Block Formatting Context)直译为”块级格式化上下文”。也就是说,它是一个独立的渲染区域。即是块盒子(Box)的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

不过,在我们 BFC 深入之前,我们先来看看常规流(Normal Flow),当然,我们也可以叫做文档流,因为也可用于文档排列布局。

二、常规流与非常规

2.1 常规流

在常规流中,他们都有一下特点:

  • 内联盒子水平排列,直到当行被占满之后换行。只有水平外边距、边框和内边距会被保留。
  • 块级盒子占满一行,下一个自动往下补齐。同级盒子间的垂直距离会由**margin**属性决定。相邻两个块级盒子之间的垂直间距会遵循外边距折叠原则被折叠。
  • 各盒子元素按照其在 HTML 中先后位置,至左向右至上而下布局。

2.2 浮动

当然,有常规流,就会有不常规流,浮动(Float)就是一个例子。当一个元素浮动之后,它会被移出正常的文档流,然后向左或者向右平移,一直平移直到碰到了所处的容器的边框,或者碰到另外一个浮动的元素。float CSS 属性指定一个元素应沿其容器的左侧或右侧放置,允许文本和内联元素环绕它。

这里就不再详细的去介绍浮动的各个属性了,想要深入了解,可以点击这里或者跳转到下面的参考资料进行阅读。

2.3 绝对定位

1
position: absolute;

上面这行代码相信很多写过前端的小伙伴们不陌生,例如,常见的置顶按钮可以用绝对定位去实现,绝对定位中,元素会被移出正常文档流,并不为元素预留空间,通过指定元素相对于最近的非 static 定位祖先元素的偏移,来确定元素位置。绝对定位的元素可以设置外边距(margins),且不会与其他边距合并。

三、BFC 可以解决什么问题

我们知道,BFC 是属于常规流,是元素的一种属性。当某个元素拥有该属性时候,就可以看成是隔离出来的独立容器。无论里面的元素怎么变化,都不会影响到外面的元素。因此我们可以用这个特性来解决问题。日常使用中,有以下条件可以触发BFC

1
2
3
4
5
6
7
1.float的值不为none

2.overflow的值不为visible

3.display的值为table-cell、tabble-caption和inline-block之一

4.position的值不为static或则releative中的任何一个

3.1 解决外部边距重叠

点我在线编辑代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="container">
<div class="box">box1</div>
</div>
<div class="container">
<div class="box">box2</div>
</div>

<style>
.box {
width: 200px;
height: 50px;
margin: 50px;
border: 1px #fff solid;
}
</style>

现在我们有两个盒子,他们是这样排列的。从图中可以看出,有 50px 不见了,这里是边距重叠了,我们可以触发 BFC 来避免这个问题。

通过设置overflow属性,从而触发 BFC,解决外部边距重叠问题。

1
2
3
.container {
overflow: hidden; /*触发BFC*/
}

3.2 清除浮动解决塌陷

点我在线编辑代码

当我们需要在一个父元素中需要写一些 item,进行包裹,然而,使用float就会导致以下结果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div class="container">
<div class="bolcks"></div>
<div class="bolcks"></div>
<div class="bolcks"></div>
</div>

<style>
.container {
border: 2px white solid;
width: 300px;
}
.bolcks {
border: 1px green solid;
float: left; /*浮动导致父元素内容塌陷*/
width: 50px;
height: 50px;
background: yellow;
}
</style>

我们希望父元素包裹所有的子元素,然而因为float脱离了正常的文档流,无法包裹,所以,我们可以通过overflow清除浮动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div class="container">
<div class="bolcks"></div>
<div class="bolcks"></div>
<div class="bolcks"></div>
</div>

<style>
.container {
border: 2px white solid;
width: 300px;
overflow: hidden; /*overflow清除浮动所带来的塌陷*/
}
.bolcks {
border: 1px green solid;
float: left; /*浮动导致父元素内容塌陷*/
width: 50px;
height: 50px;
background: yellow;
}
</style>

3.3 阻止元素被浮动元素覆盖

点我在线编辑代码

1
2
<div class="floatDiv">box1</div>
<div class="nomDiv">box2</div>
1
2
3
4
5
6
7
8
9
10
11
.floatDiv {
float: left;
width: 50px;
height: 50px;
border: 1px white solid;
}
.nomDiv {
width: 200px;
height: 200px;
border: 1px white solid;
}

同样,我们可以利用overflow触发 box2 的 BFC,从而消除浮动,达到我们想要的效果。

1
2
3
4
5
6
.nomDiv {
width: 200px;
height: 200px;
border: 1px white solid;
overflow: hidden; /*触发BFC*/
}

3.4 还有很多,这里就不一一例举啦!

看到这里,恭喜你,又获得一项不错的知识,有进步!当然,我这里只是比较肤浅的一些介绍,你可以点击参考资料继续深入阅读。

参考资料

[1] 块格式化上下文.MDN Web Docs

[2] 常规流中的块和内联布局.MDN Web Docs

[3] 浮动.MDN Web Docs

[4] 定位.MDN Web Docs