BFC概念与特性

BFC的全称是Block formatting context,直接翻译是块级格式化上下文,我喜欢把它翻译成上下文无关区域,这可能更接近它的含义,具体地说

BFC指的是页面的一个独立的渲染区域,它有自己的布局规则,其内的元素和区域外的元素互不干扰

除了内外元素相互不影响之外,BFC还存在一些独特的特性

首先,BFC不与浮动盒子重叠,并且BFC内部的浮动元素参与BFC的高度计算,从这两点特性可以看出,构建BFC是一个很好的清除浮动的手段,将包含浮动元素的父元素构建成为一个BFC可以有效地解决塌陷的问题

然后,BFC内部的块盒和行盒(行内所有元素构成行盒)会垂直沿着父元素的边框排列,相邻元素的margin会发生重叠,你可能会觉得这好像跟在body里写的排布规则是一样的,因为html根元素本身就是一个BFC

BFC触发机制

满足以下任一条件即可形成BFC

  1. body 根元素
  2. 浮动元素 (float: left/right,如果是inherit则需要继承属性非none)
  3. 绝对定位元素 (position: absolute/fixed)
  4. 特定布局方式 (display: inline-block/flex/table-cells)
  5. 溢出设置非visible (overflow: hidden/auto/scroll)

BFC用途

浮动相关

父元素塌陷问题

首先我们从特性中就可以得到一点,BFC可以很好地清除浮动,父级元素触发BFC,可以防止塌陷

塌陷的意思就是,当子元素浮动的时候,不能正常地将父元素撑开,比如下面这段代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<style>
.son {
height: 100px;
width: 100px;
float: left;
background-color: yellow;
}
.father{
background-color: pink;
width: 200px;
border: 1px solid black;
}
</style>
<body>
<div class="father">
<div class="son">
</div>
</div>
</body>

实现的效果如下图

如果我们让父元素成为bfc

1
2
3
4
5
6
.father{
background-color: pink;
width: 200px;
border: 1px solid black;
overflow:hidden;
}

就可以解决子元素浮动时父元素的塌陷问题

浮动元素覆盖问题

浮动元素是脱离文档流的,因此会和文档流元素出现重叠的情况

比如下列代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<style>
.b1 {
height: 100px;
width: 100px;
float: left;
background-color: yellow;
}
.b2{
background-color: pink;
width: 200px;
height: 200px;
}
</style>

<body>
<div class="b1"></div>
<div class="b2"></div>
</body>

会产生如下效果

一个比较好的解决方案就是,将不希望被覆盖的元素触发BFC,使得其上下文无关 (把float盒子挤出去)

边距设置

相邻元素的间距

在文档流中,相邻元素间的margin是会重叠的,比方说,我们上下两个盒子各自设置了100px的外边距,实际上页面中两个盒子之间的距离并不会是200px而是100px

如果希望两个盒子的外边距是互不影响的,那么我们需要做的事情就是将这两个盒子放入两个相邻的BFC中,这样就能设置各自的外边距,不会发生重叠

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<style>
.b1 {
height: 100px;
width: 100px;
background-color: yellow;
margin: 100px;
}
.b2{
background-color: pink;
width: 100px;
height: 100px;
margin: 100px;
}
.bfc{
overflow: hidden;
}
</style>

<body>
<div class="bfc">
<div class="b1"></div>
</div>
<div class="bfc">
<div class="b2"></div>
</div>
</body>


父子元素margin重叠

在垂直方向上,父子元素的margin也是会重叠的,比如在子元素设置一个margin,则父元会共用这个margin

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<style>
.b0{
height: 100px;
width: 300px;
background-color: brown;
}
.b1 {
height: 100px;
width: 100px;
background-color: yellow;
}
.b2{
background-color: pink;
width: 50px;
height: 50px;
margin: 25px;
}
</style>

<body>
<div class="b0"></div>
<div class="b1">
<div class="b2"></div>
</div>
</body>

这简直就是浏览器解析设计中的bug,不过好在我们有方法解决这个问题

如果我们希望这个margin设置的是子元素和父元素的距离,则需要将父元素变为BFC