在我看来,我觉得BFC是比较抽象的东西,虽然平时经常碰到,但是如果不结合实际例子单单讲概念性的东西,可能很难理解透彻。所以下文将在对BFC有一个基本的认识后引入实例进行讲解。
什么是BFC
BFC(Block Formatting Context)是Web页面中盒模型布局的CSS渲染模式,指一个独立的渲染区域或者说是一个隔离的独立容器。
产生BFC的条件
- 根元素或其它包含它的元素;
- 浮动元素,float除none以外的值;
- 绝对定位元素,position(absolute,fixed);
- display为以下其中之一的值:inline-block,table-cell;
- overflow除了visible以外的值(hidden,auto,scroll);
- 弹性盒布局flex(元素的display: flex或inline-flex)。
最常见的就是overflow:hidden、float:left/right、position:absolute,也就是当我们看到这些属性的时候,就代表了该元素已经创建了一个BFC。
BFC的范围
一个BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素。
<div id="div_1" class="BFC_1">
<div id="div_2">
<div id="div_3"></div>
<div id="div_4"></div>
</div>
<div id="div_5" class="BFC_2">
<div id="div_6"></div>
<div id="div_7"></div>
</div>
</div>
上面的代码表示,#div_1创建了一个块格式上下文BFC_1,这个上下文包括了#div_2,#div_3,#div_4,#div_5。但是由于#div_5创建了BFC_2,所以#div_6,#div_7就被排除在BFC_1之外。
这从另一方角度说明,一个元素不能同时存在于两个BFC中。
BFC的效果
- 内部的盒子会在垂直方向一个接一个排列(可以看作BFC中有一个常规流);
- 计算BFC的高度时,浮动元素也参与计算;
<style>
.box{
background:#888;
height: 100%;
}
.div_1{
background: rgb(248, 52, 248);
width: 100px;
height: 200px;
float: left;
border: 2px solid #F31264;
}
.div_2{
background: #e0f144;
width: 100px;
height: 100px;
border: 2px solid #F31264;
opacity: .5;
}
</style>
<div class="box">
<div class="div_1"></div>
<div class="div_2"></div>
</div>

如图,可以看到,.div_1向左浮动,它创建了一个BFC。同时,由于.box并没有创建BFC,因此在计算高度的时候,并没有考虑.div_1的区域,发生了高度坍塌,这也是我们经常遇到的问题。
现在我们给上面的.box创建一个BFC看看会发生什么。
<style>
.BFC{
overflow: hidden;
}
.box{
background:#888;
height: 100%;
}
.div_1{
background: rgb(248, 52, 248);
width: 100px;
height: 200px;
float: left;
border: 2px solid #F31264;
}
.div_2{
background: #e0f144;
width: 100px;
height: 100px;
border: 2px solid #F31264;
opacity: .5;
}
</style>
<div class="box BFC">
<div class="div_1"></div>
<div class="div_2"></div>
</div>
.box创建了一个新的BFC后,高度发生了变化,计算高度时它将.div_1区域也考虑进去了。

3.处于同一个BFC中的元素相互影响,比如经典的垂直外边距塌陷;
<style>
.BFC{
overflow: hidden;
}
.div_1{
background: #000;
width: 100px;
height: 100px;
margin-bottom: 20px;
}
.div_2{
background: #000;
width: 100px;
height: 100px;
margin-top: 10px;
}
</style>
<div class="BFC">
<div class="div_1"></div>
<div class="div_2"></div>
</div>
在常规文档流中,两个兄弟盒子之间的垂直距离是由他们的外边距所决定的,但不是他们的两个外边距之和,而是以较大的为准。如图:

既然存在这个问题,那有什么办法解决呢?答案是肯定的。先引入另一条BFC的效果(第4):BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,同样外面的元素不会影响到BFC内的元素。
所以在这里,我们让.div_1或.div_2再处于另一个BFC中就行了。
.BFC{
overflow: hidden;
}
.div_1{
background: #000;
width: 100px;
height: 100px;
margin-bottom: 20px;
}
.div_2{
background: #000;
width: 100px;
height: 100px;
margin-top: 10px;
}
<div class="BFC">
<div class="BFC">
<div class="div_1"></div>
</div>
<div class="div_2"></div>
</div>
这样就解决了外边距塌陷的问题,如图:

4.BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
5.浮动盒区域不叠加到BFC上。
.BFC{
overflow: hidden;
}
.box{
background: #3ff18f;
width:400px;
min-height: 100px;
}
.div_1{
background: rgb(248, 52, 248);
width: 100px;
height: 100px;
margin-right: 20px;
float: left;
border: 2px solid #F31264;
}
.div_2{
background: #e0f144;
width: 100px;
height: 200px;
border: 2px solid #F31264;
opacity: .5;
float: left;
}
<div class="BFC">
<div class="div_2"></div>
<div class="box">
<div class="div_1"></div>
<div class="div_1"></div>
<div class="div_1"></div>
</div>
</div>

可以看到,由于.box没有创建新的BFC,他内部.div_1块受到了.div_2的影响,被挤到右边去了。现在我们来给.box创建一个新的BFC解决这个问题:
<div class="BFC">
<div class="div_2"></div>
<div class="box BFC">
<div class="div_1"></div>
<div class="div_1"></div>
<div class="div_1"></div>
</div>
</div>

看!现在.box也是一个BFC,不会受到左边.div_2的挤压了,而且也不会发生重叠了。
总结
看到这里,我们也发现了其实这东西无处不在,只是平时经常忽略,没有系统的归纳学习。这次总算是理解得透彻了!
参考文章
学习 BFC (Block Formatting Context)