浅谈BFC
1. BFC的定义
BFC - Block Formatting Context 块级格式化上下文 BFC的定义,在官方文档到中,是这么介绍BFC的。
A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context.
翻译过来便是:一个BFC区域包含创建该上下文元素的所有子元素,但是不包括创建了新的BFC的子元素的内部元素。
比如:
1 | <div class="box1" id="bfc1"> |
以上面这段代码来解释,#bfc1是一块 BFC 区域,这块区域包括了box2、box3、box4、box5,但是并不包括box5下的子元素box6、box7、box8。而#bfc2也是一块 BFC 区域,包括了box6、box7、box8。所以,每一个BFC区域只包括其子元素,不包括其子元素的子元素。
2. BFC的触发条件
并不是任意一个元素都可以被当做BFC,只有当这个元素满足以下任意一个条件的时候,这个元素才会被当做一个BFC。
body根元素
设置浮动,不包括none
设置定位,absoulte或者fixed
行内块显示模式,inline-block
设置overflow,即hidden,auto,scroll
表格单元格,table-cell
弹性布局,flex
比如:
1 | <body> |
首先,以上的代码中,body元素是一个BFC,因为他满足BFC的第一个触发条件(body根元素)。但是#bfc并不是一个BFC区域,因为他并没有满足任何一个触发条件。如果我们要使他变为一个BFC区域,让其满足任意一个触发条件即可。
比如:
1 | <style> |
当#bfc元素设置为 overflow: hidden 后,满足触发条件,此时#bfc就是一个BFC区域,这个BFC区域包括box4和box5。
3. BFC解决问题
理解了BFC的触发条件后,就需要使用BFC的特点来解决布局时遇到的问题了。
首先要明白BFC有一个特点:每一个BFC区域都是相互独立,互不影响的。
3.1 解决外边距的塌陷问题
我们设置两个class值为box的div盒子,并把他的margin设置为100px
1 | <body> |
1 | <style> |
这时你会发现,我们对.box设置了四个方向的margin,都为100px。那么上一个盒子和下一个盒子之间的距离应该是 100px+100px=200px。但事实并非如此,上下两个盒子之间的距离只有100px。

这就是margin的塌陷,两段margin重叠到了一块,互相影响。那么要解决这个问题,就要用到BFC的特点:每一个BFC区域都是相互独立,互不影响的。所以,我们可以将这两个盒子放到两个BFC区域中
1 | <body> |
1 | <style> |
3.2 利用BFC解决包含塌陷
当一个父子关系的盒子,给子元素添加margin-top,会带着父元素盒子一起
1 | <body> |
1 | <style> |
原本是子元素盒子与父元素盒子顶部距离50px,由于margin塌陷问题,导致盒子的内部布局影响到了外部。

这时候,我们可以通过触发BFC,把父元素盒子变为一个BFC区域,由于BFC的特点:每一个BFC区域都是相互独立,互不影响的。 外面的父元素BFC区域影响不了bodyBFC区域,就不会改变外部布局了。
1 | .father { |
3.3 当浮动产生影响的时候,可以利用BFC来清除浮动的影响
设置一个没有设高度的父元素盒子,包含6个子元素
1 | <body> |
1 | <style> |

当给所以子元素都设置浮动后,父元素就会失去原有的高度
1 | .son{ |

所以,我们可以触发BFC,来清除浮动带来的影响
1 | .father { |

3.4 BFC可以阻止标准流元素被浮动元素覆盖
设置红色盒子浮动,蓝色盒子标准流
1 | <body> |
1 | <style> |
可以看到,红色盒子浮动覆盖了蓝色盒子

但是如果蓝色盒子触发了BFC
1 | .blue{ |

可以看到,蓝色盒子触发了BFC后,浮动元素无法覆盖蓝色盒子了,并且我们还可以利用这个特性来实现蓝色盒子的自适应功能。
4. 总结
一个BFC区域只包含其子元素,不包括其子元素的子元素。
并不是所有的元素都能成为一块BFC区域,只有当这个元素满足条件的时候才会成为一块BFC区域。
不同的BFC区域之间是相互独立的,互不影响的。利用这个特性我们可以让不同BFC区域之间的布局不产生影响。