简介
BFC全称Block Formatting Context——块级格式化上下文
它是一块独立的渲染区域,规定了在该区域内常规流块盒的布局方式
- 常规流块盒在水平方向上,必须撑满包含块
- 常规流块盒在包含块的垂直方向上依次摆放
- 常规流块盒若外边距无缝相邻(没有
border或padding阻隔),则进行外边距合并 - 常规流块盒的自动高度和摆放位置,无视浮动元素
什么条件下会创建BFC渲染区域?
这个区域由某个HTML元素创建,以下元素会在其内部创建BFC区域:
先列举一些比较常用的:
-
根元素,意味着
html元素创建的BFC区域- 几乎覆盖了网页中所有的元素,所以我们看到的常规流块盒基本都遵循上面所说的布局方式
- 浮动(
float属性不为none)元素 - 绝对定位(
position属性为absolute或fixed)元素 - 行内块元素(
display属性为inline-block) - 弹性元素(
display属性为flex或inline-flex的元素以及它们的直接子元素) overflow不等于visible的块盒
下面是一些不常用的:
| 名称 | 如何产生 | 备注 |
|---|---|---|
| 表格元素 | 表格元素默认display属性即是BFC | 表格单元格、表格标题也是 |
| 网格元素 | display属性为grid或inline-grid元素的直接子元素 | 新特性用得少 |
| 多列容器 | 元素的column-count或column-width不为auto,包括 column-count为1 | 新特性用得少 |
| display属性 | display属性值为flow-root的元素,flow-root: 一个新的display属性的值,它可以创建无副作用的BFC | 用得少 |
| contain属性 | contain属性值为layout、content、paint的元素 | 用得少 |
创建BFC区域的元素自身并不在该区域内
下图中的元素分别在谁创建的BFC区域内?
-
根元素创建的BFC
元素A、元素C、元素E、元素F、元素G
-
元素A创建的BFC
元素B
-
元素C创建的BFC
元素D
-
元素G创建的BFC
元素H
什么叫做独立的渲染区域?
不同的BFC区域,他们进行渲染时互不干扰,因为创建BFC的元素,隔绝了它内部和外部的联系,内部的渲染不会影响到外部。也就是说,创建了BFC 的元素可以看作是隔离了的独立容器,容器里面的元素在布局上不会影响到外面的元素,并且创建了BFC的容器具有普通容器所没有的一些特性,具体规则如下:
创建BFC的元素,它的自动高度需要计算浮动元素
<style>
.father {
background-color: yellow;
}
.son {
float: left;
width: 200px;
height: 200px;
margin: 20px;
background-color: red;
}
</style>
<body>
<div class="father">
<div class="son"></div>
<div class="son"></div>
</div>
</body>
由于父盒子是一个常规流块盒,根据常规流块盒的特性,计算自动高度时会无视浮动元素,最终计算出的高度为0,自然展示不出背景颜色,这种现象被称为高度坍塌
那么有哪些方法可以让父元素的高度被浮动的元素撑开呢?
- 普通清除浮动的方法
<style>
.father {
background-color: yellow;
}
.clearfix::after {
content: '';
display: block;
clear: both;
}
.son {
float: left;
width: 200px;
height: 200px;
margin: 20px;
background-color: red;
}
</style>
<body>
<div class="father clearfix">
<div class="son"></div>
<div class="son"></div>
</div>
</body>
- 让父元素创建BFC
还有很多让父元素创建BFC的方式,我这里就演示一个最简单的方法,通过overflow: hidden属性创建,该方法同样也是所有创建BFC的方法中副作用最小的一种,并不会过度影响我们的布局,但只针对高度坍塌这个问题来讲,个人还是推荐普通清除浮动的方法
<style>
.father {
overflow: hidden;
background-color: yellow;
}
.son {
float: left;
width: 200px;
height: 200px;
margin: 20px;
background-color: red;
}
</style>
从浏览器显示的结果可以看到父元素已经有了高度,黄色背景色也显示了出来
创建BFC的元素,不会与浮动元素重叠
<style>
.son1 {
float: left;
width: 200px;
height: 200px;
background-color: red;
}
.son2 {
height: 400px;
background-color: #000;
}
</style>
<body>
<div class="father">
<div class="son1"></div>
<div class="son2"></div>
</div>
</body>
由于son2是根元素下的常规流块盒子,其有个特点就是无视浮动元素,所以肯定会与浮动元素son1重叠
那么有哪些方法可以让浮动元素son1和常规流块盒子son2不重叠呢?
- 让son2创建BFC
我们还是采用最简单的创建BFC的方式:overvflow: hidden,由于创建BFC的元素具有不会和浮动元素重叠的特性,所以其会和son1分开。另外补充一点,创建了BFC后的son2依然是根元素BFC区域内的常规流块盒子,所以它一定会撑满包含块,但现在浮动元素占了一块位置,所以son2盒子的margin-left属性就会自动填满包含块
<style>
.son1 {
float: left;
width: 200px;
height: 200px;
background-color: red;
}
.son2 {
height: 400px;
background-color: #000;
overflow: hidden;
}
</style>
<body>
<div class="father">
<div class="son1"></div>
<div class="son2"></div>
</div>
</body>
从显示结果来看,son2已经与浮动元素son1不再重叠,而且再去设置son2元素的margin-left值也不会生效,这种方法通常在布局中称为两栏布局
创建BFC的元素,不会和它的子元素进行外边距合并
<style>
.father {
width: 600px;
height: 600px;
margin-top: 10px;
background-color: red;
}
.son {
width: 300px;
height: 300px;
margin-top: 50px;
background-color: #000;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
从下图中可以看出,父元素和子元素的顶部在同一水平线上,而且距离顶部距离为50px,并非10+50 = 60px,很明显产生了外边距折叠现象
那要怎么样才能消除外边距折叠,让子盒子距离父盒子顶部为50px,父盒子距离顶部10px呢?
- 为父元素加上透明的边框
常规流块盒中有个特点就是只有当外边距无缝相邻(没有border或padding阻隔)的时候,才会进行外边距合并,所以我们只要使用border边框做一个隔离就可以让两个常规流块盒不产生边距合并
<style>
.father {
width: 600px;
height: 600px;
margin-top: 10px;
background-color: red;
border-top: 1px solid transparent;
}
.son {
width: 300px;
height: 300px;
margin-top: 50px;
background-color: #000;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
这样看样子效果是实现了,其实也有点瑕疵,因为border还是占了盒子位置的,多多少少对布局有一点影响
- 将父元素的margin值改为padding值
和第一种方法的原理一样,使用padding区域填充是不会产生边距合并的效果的
<style>
.father {
width: 600px;
height: 600px;
padding-top: 10px;
background-color: red;
}
.son {
width: 300px;
height: 300px;
margin-top: 50px;
background-color: #000;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
这样子父元素顶部的空间就是由padding来撑起的,有个不足就是背景颜色是会包括我们的padding区域的,所以如果还有设置背景颜色的需求,建议使用其它方法
- 为父元素创建BFC
这里还是用我们最熟悉的overflow: hidden属性为元素创建BFC
<style>
.father {
width: 600px;
height: 600px;
margin-top: 10px;
background-color: red;
overflow: hidden;
}
.son {
width: 300px;
height: 300px;
margin-top: 50px;
background-color: #000;
}
</style>
<body>
<div class="father">
<div class="son"></div>
</div>
</body>
因为创建了BFC的元素是不会和它的子元素发生外边距合并的,最终我们就看到了希望的效果
这个规则还可以这样解释:处在不同BFC区域的元素,他们的外边距不会合并,只有在同一个BFC区域内,他们的外边距才会合并
因为当父元素创建了BFC后,son元素处在father元素的所创建的BFC区域内,但father元素其实是在根元素所创建的BFC区域内的,所以子元素和父元素所在的BFC区域不同,它们的外边距自然是不会合并的