一、什么是BFC
BFC: 块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,
是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域
引用MDN
二、BFC生成条件
-
根元素()
-
浮动元素(元素的 float 不是 none)
-
绝对定位元素(元素的 position 为 absolute 或 fixed)
-
overflow 值不为 visible 的块元素
-
display 值为 flow-root 的元素
-
弹性元素(display为 flex 或 inline-flex元素的直接子元素)
-
行内块元素(元素的 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)
-
contain 值为 layout、content或 paint 的元素
-
网格元素(display为 grid 或 inline-grid 元素的直接子元素)
-
多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
-
column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
引用MDN
三、BFC特性
- 内部盒子在垂直方向上 一个接一个排练
- 内部盒子在垂直方向上会出现上下margin重叠,间距以较大为准
- BFC区域不会与float浮动元素重叠
- 计算BFC区域高度时,浮动元素也参与计算
- BFC是页面上一个独立的容器,容器里面的元素不会影响外面的元素,反之也如此
注意
父子元素margin重叠问题,可以通过给父元素设置overflow:hidden,使其形成一个BFC区域即可解决
3.1 内部盒子在垂直方向上会出现上下margin重叠,间距以较大为准
<head>
<style type="text/css">
.container {
width: 100px;
height: 100px;
background-color: red;
overflow: hidden;
}
.box1 {
width: 30px;
height: 30px;
margin-bottom: 10px;
background-color: green;
}
.box2 {
width: 30px;
height: 30px;
margin-top: 20px;
background-color: orange;
}
</style>
</head>
<body>
<div class="container">
<div class="box1"></div>
<div class="box2"></div>
</div>
</body>
如图
以上示例给container盒子设置overflow:hidden形成BFC,内部的两个盒子就会出现上下margin重叠现象,
两个盒子的间距取margin较大值
3.1.1 假如不给container盒子设置overflow:hidden会怎样呢?
box1和box2还是会出现上下margin重叠现象,因为整个根元素就是一个BFC区域
3.1.2 如何让两个盒子的margin都生效?
若要两个盒子的margin都生效则需要让两个盒子在不同的BFC里,即需要给box1或box2再嵌套一层并设置overflow:hidden,形成一个新的BFC。
直接给box1或box2设置overflow:hidden则不会生效,因为只有BFC容器里面的元素才不会影响外面的元素,而像box1和box2兄弟元素是属于外层container的子元素,还是会相互影响的
解决方法:对box1再嵌套一层
.wrapper {
overflow: hidden;
}
<div class="container">
<div class="wrapper">
<div class="box1"></div>
</div>
<div class="box2"></div>
</div>
如图
3.2 BFC区域不会与float浮动元素区域重叠
3.2.1 默认情况下
标准流中的元素会与float浮动元素重叠,即每个元素的左边都会与包含该盒子的父元素左边对齐
如:box1盒子为浮动元素,box2为标准流中元素,它们都与container盒子左边对齐。
但虽然浮动元素与后续的块级元素重叠了,但块级元素中的文本、块级元素内的行内元素、块级元素内的行内块元素都不会被遮挡,从而形成我们常见的如:字围现象
<head>
<style type="text/css">
.container {
width: 100px;
height: 100px;
background-color: red;
}
.box1 {
width: 40px;
height: 40px;
background-color: green;
opacity: 0.5;
float: left;
}
.box2 {
width: 80px;
height: 80px;
background-color: orange;
}
</style>
</head>
<body>
<div class="container">
<div class="box1">123</div>
<div class="box2">456</div>
</div>
</body>
如图
3.2.2 BFC区域不会与float浮动元素区域重叠
为box2盒子添加属性overflow: hidden 让其形成BFC区域,其他不变
.box2 {
width: 40px; //修改宽度为40px
height: 40px; //修改高度为40px
background-color: orange;
overflow: hidden; //新增加的属性
}
如图
3.2.3 此时如果给box2盒子再多设置一个属性margin-left: 10px会怎样呢?
.box2 {
width: 40px;
height: 40px;
background-color: orange;
overflow: hidden;
margin-left: 10px; //新增加的
}
如图:不会变
是不是很疑惑,既然BFC区域不会与float浮动元素区域重叠,那么给box2盒子设置的左边距应该是以box1盒子为参照物啊,为什么左边距没有出现?
我的理解是,虽然BFC区域特性是不会与float元素区域重叠,但BFC区域内的 块级元素 的参照物还是以标准流中的元素为准,所以此时box2盒子是以container盒子为参照物
3.2.4 如果给box2盒子设置margin-left: 50px;则会看到box2盒子和box1盒子有10px的距离
如图
3.2.5 此时如果为box2盒子添加属性display: inline-block 同样让其形成BFC区域,再为其添加margin-left: 10px属性,那会不会和上面一样,也不出现左边距呢?
.box2 {
width: 40px;
height: 40px;
background-color: orange;
display: inline-block; //新增加的
margin-left: 10px; //新增加的
}
如图:
是不是又疑惑了?为什么这次又出现了左边距呢?这都什么情况
我的理解是:浮动流对后续标准流中的行内块元素或行内元素都会视为文本,而浮动流不会遮挡文本,所以它们会沿着浮动流的同一行继续外后排
也就是说浮动元素的脱标有字围现象,而它的字围现象不仅仅只针对文字,这种现象也会把行内和行内块元素也当作文字,所以我们不能直接无视浮动元素的存在
3.2.6 自适应两栏布局
根据BFC区域不会与float浮动元素区域重叠的特性,可以制作出自适应两栏布局
<head>
<style type="text/css">
.container {
width: 100px;
height: 100px;
background-color: red;
}
.box1 {
width: 40px;
height: 40px;
background-color: green;
float: left;
}
.box2 {
height: 40px;
background-color: orange;
overflow: hidden;
}
</style>
</head>
<body>
<div class="container">
<div class="box1">123</div>
<div class="box2">456</div>
</div>
</body>
如图
3.3 计算BFC区域的高度时,浮动元素也参与计算
3.3.1 默认情况下
标准流元素是无法包裹住浮动元素的,这也就导致浮动元素无法参与父元素高度的计算,也就出现了我们常说的 高度塌陷问题
<head>
<style type="text/css">
.container {
width: 100px;
border: 1px solid red;
}
.box1 {
width: 40px;
height: 40px;
background-color: green;
opacity: 0.5;
float: left;
}
</style>
</head>
<body>
<div class="container">
<div class="box1">123</div>
</div>
</body>
如图
3.3.2 BFC区域能够包裹住浮动的子元素,因此浮动元素也参与BFC区域下高度的计算,从而也解决了高度塌陷问题
为container盒子添加属性overflow: hidden 让其形成BFC区域,其他不变
.container {
width: 100px;
overflow: hidden;
border: 1px solid red;
}
如图
BFC中浮动流和定位流区别
- 1: 浮动流脱标有字围现象,不仅针对块级元素的文本,对后续标准流中的行内块元素、行内元素也都会视为文本,并不会遮挡它们,会让它们沿着浮动元素同一行往后排
- 2: 定位流脱标会直接遮挡标准流,无论是块级元素还是行内元素