BFC
块格式化上下文(Block Formatting Context,BFC) 是 Web 页面的可视化 CSS 渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
下列方式会创建块格式化上下文:
- 根元素(
<html>
) - 浮动元素(元素的
float
不是none
) - 绝对定位元素(元素的
position
为absolute
或fixed
) - 行内块元素(元素的
display
为inline-block
) - 表格单元格(元素的
display
为table-cell
) - 表格标题(元素的
display
为table-caption
) - 匿名表格单元格元素(元素的
display
为table
、inline-table
) -
display
值为flow-root
的元素(兼容性不好) - 弹性元素(
display
为flex
或inline-flex
元素的直接子元素) - 元素(
display
为grid
或inline-grid
元素的直接子元素) -
overflow
值不为visible
的块元素
上述创建BFC的CSS列为以下几类:
-
html
根元素 -
float
(不为none
即可)left
right
-
position
absolute
fixed
-
display
inline-block
flex、inline-flex
grid、inline-grid
-
table
、table-cell
、table-caption
flow-root
块格式化上下文对浮动定位(参见 float)与清除浮动(参见 clear)都很重要。
总结:
- 浮动定位和清除浮动时只会应用于同一个 BFC 内的元素,浮动不会影响其它 BFC 中元素的布局;
- 而清除浮动只能清除同一 BFC 中在它前面的元素的浮动;
- 外边距折叠(Margin collapsing)也只会发生在属于同一 BFC 的块级元素之间;
- BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,反之亦然;
- 计算BFC的高度时,考虑BFC所包含的所有元素,连浮动元素也参与计算;
- 浮动盒区域不叠加到BFC上;
高度坍塌和清除浮动
高度坍塌是指父元素本来应该包括子元素的高度,但是实际上父元素比子元素的高度要小。
web前端开发学习Q-q-u-n: 731771211,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
<!DOCTYPE html>
<html lang="en">
<head>
<style>
.container {
margin-left: 50px;
background: red;
}
.box1 {
float: left;
width: 200px;
height: 200px;
background-color: blue;
}
.box2 {
width: 400px;
height: 100px;
background: cyan;
}
</style>
</head>
<body>
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
</html>
1、box1
浮动之后,父元素的高度就坍塌了,解决办法是让父元素触发 BFC ,这样 BFC 内的元素就无法影响到外面了,给 container
加上 overflow: auto;
即可。加上之后变成这样了。
2、也可以通过给 container
添加 ::after
伪元素,清除左右浮动来防止坍塌。
.container::after {
content: "";
display: block; /* 不能少 */
clear: left;
}
3、还可以通过在父元素的最后添加一个块级元素并清除浮动。
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
<div style="clear: both;"></div>
</div>
4、图中有另外一个问题是 box2
被 box1
盖住了一部分,这是因为 box1
浮动起来了,显然只需要清除浮动即可。使用 BFC 清除,对应的规则是 浮动盒区域不叠加到BFC上,给 box2
添加 overflow: auto;
之后显示正常。
5、同样我们也可以通过 clear:both;
来清除浮动,只需要给 box2
添加 clear: both;
,但是效果和 BFC 清除有点不一样,因为 clear: both;
表示元素下移清除左右浮动。
外边距折叠
块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的最大者,这种行为称为外边距折叠(margin collapsing),有时也翻译为外边距合并。注意浮动元素和绝对定位元素的外边距不会折叠。
外边距折叠的基本情况:
相邻元素之间 毗邻的两个元素之间的外边距会折叠(除非后一个元素需要清除之前的浮动)。
父元素与其第一个或最后一个子元素之间 如果在父元素与其第一个子元素之间不存在边框、内边距、行内内容,也没有创建块格式化上下文、或者清除浮动将两者的 margin-top 分开;或者在父元素与其最后一个子元素之间不存在边框、内边距、行内内容、height、min-height、max-height 将两者的 margin-bottom 分开,那么这两对外边距之间会产生折叠。此时子元素的外边距会“溢出”到父元素的外面。
从上面一段话总结下可以去除外边距折叠的方法:
- 父元素添加边框(border);
- 父元素添加内边距(padding);
- 父子元素之间存在行内元素
<span>
匿名元素
; - 父子元素之间存在触发 BFC 的元素(插入一个
display: flex
的块级元素); - 父元素触发 BFC(
overflow: auto;
等);
外边距折叠的一些规则:
- 即使某一外边距为 0,这些规则仍然适用。因此就算父元素的外边距是 0,第一个或最后一个子元素的外边距仍然会“溢出”到父元素的外面。
- 如果参与折叠的外边距中包含负值,折叠后的外边距的值为最大的正边距与最小的负边距(即绝对值最大的负边距)的和。
- 如果所有参与折叠的外边距都为负,折叠后的外边距的值为最小的负边距的值。这一规则适用于相邻元素和嵌套元素。
以下面代码为例:
web前端开发学习Q-q-u-n: 731771211,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
<style>
.container {
background-color: deeppink;
}
.child {
}
div {
background-color: cyan;
}
body {
margin: 0;
background-color: yellow;
}
</style>
</head>
<body>
<div class="container" style="margin-top: 10px;">
<div class="child" style="margin-top: 50px;">word</div>
</div>
</body>
</html>
由于外边距折叠且外边距都为正,所以取大的 50px
1、给 container
添加 border
,成功去除折叠。
.container {
background-color: deeppink;
border: 1px solid #000000;
}
2、给父元素增加 padding
,正常了。
.container {
background-color: deeppink;
padding: 1px;
}
3、给父子元素之间添加内联或者匿名元素,添加一个
,去除折叠了,但是新增的元素会占据额外的空间,所以不推荐。
<div class="container" style="margin-top: 10px;">
<div class="child" style="margin-top: 50px;">word</div>
</div>
4、父子元素之间添加触发了 BFC 的元素,正常了。
web前端开发学习Q-q-u-n: 731771211,分享学习的方法和需要注意的小细节,不停更新最新的教程和学习方法(详细的前端项目实战教学视频,PDF)
<div class="container" style="margin-top: 10px;">
<div style="display: flex;"></div>
<div class="child" style="margin-top: 50px;">word</div>
</div>
5、父元素触发 BFC,正常了。
.container {
background-color: deeppink;
overflow: auto;
}
今天的文章就到这里,感谢阅读~