# 什么是BFC
BFC 全称:Block Formatting Context, 名为 "块级格式化上下文"。
W3C对BFC的定义如下: 浮动元素和绝对定位元素,非块级盒子的块级容器(例如 inline-blocks, table-cells, 和 table-captions),以及overflow值不为"visiable"的块级盒子,都会为他们的内容创建新的BFC(Block Fromatting Context, 即块级格式上下文)。
W3C官方解释为:BFC它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,Block Formatting Context提供了一个环境,HTML在这个环境中按照一定的规则进行布局。
简单说:BFC称为块级格式化上下文,是CSS中的一种渲染机制。是一个拥有独立渲染区域的盒子(也可以理解为结界),规定了内部元素如何布局,并且盒子内部元素与外部元素互不影响。
# 触发条件
下列方式会创建块格式化上下文:
- 根元素(
<html>) - 浮动元素(元素的 float 不是 none)
- 绝对定位元素(元素的 position 为 absolute 或 fixed)
- 行内块元素(元素的 display 为 inline-block)
- 表格单元格(元素的 display 为 table-cell,HTML表格单元格默认为该值)
- 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
- 匿名表格单元格元素(元素的 display 为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot 的默认属性)或 inline-table)
- overflow 计算值(Computed)不为 visible 的块元素
- display 值为 flow-root 的元素
- contain 值为 layout、content 或 paint 的元素
- 弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)
- 网格元素(display 为 grid 或 inline-grid 元素的直接子元素)
- 多列容器(元素的 column-count 或 column-width (en-US) 不为 auto,包括 column-count 为 1) column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中
猛一看上面的这些是不是瞬间懵逼了,我去,咋这么多,这里我们可以简单记住几个常用的的 CSS 属性:
- overflow: hidden
- display: inline-block
- position: absolute
- position: fixed
- display: table-cell
- display: flex
# BFC的规则
- BFC就是一个块级元素,块级元素会在垂直方向一个接一个的排列
- BFC就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签
- 垂直方向的距离由margin决定, 属于同一个BFC的两个相邻的标签外边距会发生重叠
- 计算BFC的高度时,浮动元素也参与计算
# BFC的应用场景
# 使用Float脱离文档流,高度塌陷
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>高度塌陷</title>
<style>
.box {
width: 100px;
height: 100px;
background: red;
}
.container {
background: orange;
}
</style>
</head>
<body>
<div class="container">
<div class="box"></div>
</div>
</body>
</html>
上述代码运行效果如下:
下里面给 .box 设置 float: left; 再次运行代码,效果展示如下:
咦,container 怎么看到不到了?它跑哪里去了呢?从上面的代码可以看出我们并没有给 container 设置高度,它的高度是由 box 撑开的,当我们给 box 设置了浮动,使其脱离了文档流,使得container的高度没有被撑开。我们可以通过上面的触发条件来给 container 触发 BFC,这里使用 overflow: hidden;
.container {
background: orange;
overflow: hidden;
}
运行代码,可以看到 container 又出现了。
# Margin边距重叠
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.box {
width: 100px;
height: 100px;
background: red;
}
.box1 {
margin-bottom: 20px;
}
.box2 {
margin-top: 100px;
}
</style>
</head>
<body>
<div class="container">
<div class="box box1">box1</div>
<div class="box box2">box2</div>
</div>
</body>
</html>
在上面的代码中我们分别给 box1 设置了margin-bottom:20px; 给 box2 设置了 margin-top:100px; 我们的想法是让两个 box 上下相距 120px; 但实际效果却如下:

从图上可以看出两个 box 之间相距了 100px ,也就是取了两个 margin 中的最大的值,不是两个 margin 的和,解决这个问题我们可以使用BFC。给 box1 设置 display:inline-block;
.box1 {
margin-bottom: 20px;
display: inline-block;
}
运行结果如下:

可以看到 margin 的塌陷的问题被修复了。当然,还有其他方法,大家可以试试。
# 两栏布局
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>两栏布局</title>
<style>
div {
width: 200px;
height: 100px;
border: 1px solid red;
}
</style>
</head>
<body>
<div style="float: left;">
两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局两栏布局
</div>
<div style="width: 300px; color:red;">
白日依山尽,黄河入海流。欲穷千里目,更上一层楼。墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。
</div>
</body>
</html>
代码运行效果如下:

可以通过给第二个 div 设置 display:inline-block; 将其设置成一个 BFC。
<div style="width: 300px; color:red;display: inline-block;">
白日依山尽,黄河入海流。欲穷千里目,更上一层楼。墙角数枝梅,凌寒独自开。遥知不是雪,为有暗香来。
</div>
运行效果如下:

参考: