理解BFC(二)

理解BFC(二)

在上一篇文章理解BFC(一)中,我们学习了什么是BFC,即BFC会有什么样的行为。今天我们来说说BFC有什么用以及什么时候会创建BFC。

BFC的作用

防止margin折叠

下面是一个margin折叠的例子:

<style>
.container {
background: yellow;
}
.inner {
background: blue;
width: 100px;
height: 100px;
margin: 50px;
}
</style>
<div class="container">
<div class="inner"></div>
</div>

我们可以看到,在inner设置了margin之后,水平方向上明显产生了50px的margin,但是垂直方向上却不是很明显。这是因为containerinner属于同一个BFC,他们的margin在垂直方向上发生了折叠。也就是说,inner的50px的margin被加到了container上,他们两个共享50px的margin。


我们再来看看下面这个例子:

<style>
.container2 {
background: yellow;
display: flow-root; /*关键点 这里创建了BFC*/
}
.inner {
background: blue;
width: 100px;
height: 100px;
margin: 50px;
}
</style>
<div class="container2">
<div class="inner"></div>
</div>

我们可以看到,现在inner像我们期望的那样,垂直方向上也产生了50px的margin。这是因为我们使用display: flow-rootcontainer2上创建了一个新的BFC(至于为什么这样能创建BFC,后面再说),使得innercontainer处于不同的BFC。处于不同BFC的元素不会发生margin折叠。

这里我们应该思考一下,是inner处于新创建的BFC上还是container处于新创建的BFC上呢?答案是inner处于新的BFC上。

我们来看看下面这个例子:

<style>
.container3 {
background: yellow;
}
.inner3 {
display: flow-root; /*关键点 inner这里创建了BFC*/
background: blue;
width: 100px;
height: 100px;
margin: 50px;
}
</style>
<div class="container3">
<div class="inner3"></div>
</div>

这次我们不在container上创建BFC了,而是在inner上创建BFC。可以看到,margin还是发生了折叠。这是为什么呢?我们不是在inner上创建了新的BFC嘛?按道理containerinner处于不同的BFC才对?

然而containerinner还是属于同一个BFC。这是因为,我们在inner上创建BFC,其实是改变了inner内部的BFC,而inner所处的BFC并没有发生改变。在上个例子中,我们在container上创建了BFC,使得inner处于新的BFC中,但是container还是原来的BFC。因此他们属于不同的BFC,能够防止margin折叠。

撑开float

首先,我们要知道,float只发生在一个BFC的内部。也就是说,一个BFC内部的float元素不会影响到BFC外面的元素,它只会在这个BFC内部作妖。

来看下面这个例子:

<style>
.container4 {
min-height:100px;
border: 5px solid;
}
.float {
height: 200px;
width: 200px;
background: yellow;
float: left;
}
</style>
<div class="container4">
<div class="float"></div>
</div>

我们可以看到,在这个例子中,float元素没能把 container撑开。这是因为float元素脱离了文档流。同时,现在float元素位于<html>标签产生的BFC中,因此会影响到这个BFC中的所有元素。

要想把container高度撑开,只需要让container生成一个BFC:

<style>
.container5 {
min-height:100px;
border: 5px solid;
display: flow-root; /*生成BFC*/
}
.float {
height: 200px;
width: 200px;
background: yellow;
float: left;
}
</style>
<div class="container4">
<div class="float"></div>
</div>

此时,container生成了一个BFC,而float元素位于这个BFC内部,因此浏览器不允许float影响到BFC外部的元素,就会将container撑开,以便容纳下float元素。

如何生成BFC

1. <html>根元素

<html>根元素是最初始的一个BFC。

2. float元素

所有float为left或right的元素都会生成一个BFC。

3. 绝对定位元素

包括position:absoluteposition:fixedposition:sticky

2、3两点总结起来就是,所有脱离文档流的元素都会产生BFC。

4. display: inline-block

5. display: table-cell

6. display: tabel-caption

4-6点总结起来就是所有不是display:block的“块级元素”

7. overflow

所有设置了overflow不为visible的元素

8. display: flow-root

直接指定创建一个BFC,没有其他任何副作用。

9. 设置了contain: layout, content, strict

10. flex items(不是flex container)

11. grid items

12. multicol containers

13. column-span: all

Author: LeoB_O
Link: https://leob-o.github.io/2019/06/09/BlockFormatContext2/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.