什么是BFC
块格式化上下文(Block Formatting Context, 简称BFC)是Web页面的可视CSS渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
BFC具有以下几个特点:
- BFC是一个独立的布局环境,BFC内部的元素布局与外部互不影响
- 可以通过一些条件触发BFC,从而实现某些特殊的布局
BFC布局规则
BFC布局在布局时会遵从以下规则:
- 内部的块级元素会在垂直方向上一个接一个地排列(也是文档流的规则)
- 块级元素垂直方向的距离由margin决定。属于同一个BFC的两个相邻的块级元素会发生margin合并;不属于同一个BFC的两个相邻的块级元素不会发生margin合并。(可以用来解决margin重叠)
- 每个元素的margin box的左边,与包含border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是这样的
- BFC的区域不会与float box重叠。
- BFC就是页面上的一个隔离的独立容器,容器里面的元素不会影响到里面的元素,里面的元素也不会影响到外面的元素。
- 计算BFC的高度时,浮动元素也参与计算。(可以用来解决浮动导致的父元素高度塌陷的问题)
BFC形成的条件
- 根元素html
- 浮动元素的float属性不为none
- 块元素的overflow属性不为visiable和clip
- 绝对定位元素的position属性为absolute或fixed
- 行内块元素(也就是display: inline-block;)
- 表格单元格元素(也就是display: table-cell;)
- 表格标题元素(也就是display: table-caption;)
- 匿名表格单元格元素(也就是display: table或table-row或table-row-group或table-header-group或table-footer-group;)
- display值为flow-root的元素
- contain值为layout、content或paint的元素
- 弹性元素(display 值为 flex 或 inline-flex 元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器
- 网格元素(display 值为 grid 或 inline-grid 元素的直接子元素),如果它们本身既不是 flex、grid 也不是 table 容器
- 多列容器(column-count 或 column-width (en-US) 值不为 auto,包括column-count 为 1)
BFC的应用
正是因为BFC具有以上介绍的特点以及它在页面布局时遵循的规则,因此BFC常常被用于以下几个方面
解决浮动导致的高度塌陷(包含内部浮动)
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="box">我是一个块级盒子</div>
</div>
.test-wrap {
width: 400px;
border: 1px solid black;
.box {
width: 200px;
height: 200px;
float: left;
border: 1px solid lightgreen;
}
}
效果如下:
父容器发生了高度塌陷
给父容器设置一个生成BFC的属性,这里我们设置的是overflow: hidden;
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="box">我是一个块级盒子</div>
</div>
.test-wrap {
width: 400px;
border: 1px solid black;
overflow: hidden;
.box {
width: 200px;
height: 200px;
float: left;
border: 1px solid lightgreen;
}
}
效果如下:
解决margin传递的问题
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="box"></div>
</div>
.test-wrap {
width: 100px;
height: 100px;
background-color: red;
.box {
width: 50px;
height: 50px;
margin-top: 50px;
background-color: blue;
}
}
效果如下
明明是给子元素设置的margin-top,却传递给了父元素,变成了父元素有margin-top.
给父容器设置一个生成BFC的属性,这里我们设置的是display: inline-block;
效果如下:
不发生margin传递了。
解决块级元素margin重叠
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="box1">我是第一个块级盒子</div>
<div class="box2">我是第二个块级盒子</div>
</div>
.test-wrap {
width: 400px;
height: 500px;
background-color: aliceblue;
.box1 {
height: 100px;
border: 1px solid lightgreen;
margin-bottom: 30px;
}
.box2 {
height: 100px;
border: 1px solid lightblue;
margin-top: 20px;
}
}
效果如下:
两个盒子之间的距离只有30px,margin发生了重叠
给两个盒子加一层容器,然后设置生成BFC的属性,这里我们设置的是overflow: hidden;使其成为两个独立的BFC,这样就不会重叠了
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="container">
<div class="box1">我是第一个块级盒子</div>
</div>
<div class="container">
<div class="box2">我是第二个块级盒子</div>
</div>
</div>
.test-wrap {
width: 400px;
height: 500px;
background-color: aliceblue;
.box1 {
height: 100px;
border: 1px solid lightgreen;
margin-bottom: 30px;
}
.box2 {
height: 100px;
border: 1px solid lightblue;
margin-top: 20px;
}
.container {
overflow: hidden;
}
}
效果如下: 两个盒子之间的距离是50px
自定义两栏布局(排除外部浮动)
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="left-box">我是左边盒子,内容是巴拉巴拉巴拉巴拉巴拉巴拉</div>
<div class="right-box">我是右边盒子</div>
</div>
.test-wrap {
width: 400px;
height: 400px;
border: 1px solid red;
.left-box {
width: 100px;
height: 100px;
float: left;
background-color: lightblue;
}
.right-box {
background-color: lightcoral;
}
}
效果如下:
此时浮动元素会遮挡右边的元素
给右边元素设置一个生成BFC的属性,这里我们设置的是display:flow-root
<div class='test-wrap'>
<!-- BFC布局 -->
<div class="left-box">我是左边盒子,内容是巴拉巴拉巴拉巴拉巴拉巴拉</div>
<div class="right-box">我是右边盒子</div>
</div>
.test-wrap {
width: 400px;
height: 400px;
border: 1px solid red;
.left-box {
width: 100px;
height: 100px;
float: left;
background-color: lightblue;
}
.right-box {
background-color: lightcoral;
display:flow-root;
}
}
效果如下:
这样右边盒子就不会被左边盒子遮挡了。这个对应了BFC布局规则的第四点。