BFC && 外边距折叠
# BFC
BFC(Block fomatting context) = block-level box + Formatting Context
# Box
- Box即盒子模型
- block-level box即块级元素,display属性为block,list-item,table的元素,会生成block-level box;并参与block formatting content
- inline-level box即行内元素,display属性为inline,inline-block,inline-table的元素,会生成inline-level box;并参与inline formatting content
# Formatting content
- 这是W3C CSS2.1规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系、相互作用。最常见的有BFC(B为Block)和IFC(I为inline)。
- CSS2.1中只有BFC和IFC,CSS3中还增加了GFC(G为grid)和FFC(F为flex)。
# BFC定义
BFC直译为“块级格式化上下文”。它是一个独立的渲染区域,只有block-level box参与,它规定了内部的block-level box如何布局,并且与这个区域外部毫不相干。
# BFC的生成
上文提到BFC是一块渲染区域,那这块渲染区域到底在哪,它有多大,这些由生成BFC的元素决定,CSS2.1中规定满足下列CSS声明之一的元素便会生成BFC。
- html根元素
- float的值不为none
- overflow的值不为visible
- display的值为inline-block、table-cell、table-caption
- display的值为flex或inline-block、grid或inline-grid元素的直接子元素
- position的值为absolute或fixed
- contain的值为layout、content或paint
注:display: table也认为可以生成BFC,因为table默认生成一个匿名的table-cell,正是这个匿名的table-cell生成了BFC。
# BFC的特性及应用
- 同一个BFC下外边距会发生折叠
<head>
<style>
div{
width: 100px;
height: 100px;
background: lightblue;
margin: 50px;
}
</style>
</head>
<body>
<div></div>
<div></div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
如上代码,两个div元素都处于同一个BFC容器下(这里指html元素),所以两个div的外边距发生了重叠,如果想要避免外边距的重叠,可以将其放在不同的BFC容器中。
<head>
<style>
.box{
overflow: hidden;
}
.box1{
width: 100px;
height: 100px;
background: lightblue;
margin: 50px;
}
</style>
</head>
<body>
<div class="box">
<div class="box1"></div>
</div>
<div class="box">
<div class="box1"></div>
</div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- BFC可以包含浮动元素
当容器内的元素浮动时,就会脱离文档流,且有时会发生父元素高度塌陷的情况
<head>
<style>
.box {
border: 5px solid lightcoral;
}
.box1 {
width: 100px;
height: 100px;
background: lightblue;
float: left;
}
</style>
</head>
<body>
<div class="box">
<div class="box1"></div>
</div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
如果触发容器的BFC,那么容器将会包裹浮动元素(如给.box添加display: inline-block;)
- BFC可以阻止元素被浮动元素覆盖
先看一个文字环绕的效果:
<head>
<style>
.box {
width: 200px;
height: 200px;
background-color: lightcoral;
}
.box1 {
width: 100px;
height: 100px;
background-color: lightblue;
float: left;
}
</style>
</head>
<body>
<div>
<div class="box1">
我是一个浮动的元素
</div>
<div class="box">
我没有设置浮动,也没有触发BFC,假装这里文字很多,假装这里文字很多,假装这里文字很多,假装这里文字很多
</div>
</div>
</body>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
可以看到第二个div有部分被浮动元素遮挡,但文本信息会环绕着浮动元素,如果想避免元素被覆盖,可触发第二个元素的BFC特性,在.box中添加overflow: hidden;就会变成如下效果:
该方法可以用来实现两栏自适应布局,利用float+overflow:hidden;,主要思想是通过overflow触发BFC,而BFC不会与浮动元素重叠。由于设置overflow:hidden;并不会触发IE6-浏览器的haslayout属性,所以需要设置zoom:1来兼容。
# 外边距折叠
定义:块的顶部和底部边距有时被合并(折叠)成单个边距,其大小是各个边距中的最大值。外边距折叠是在垂直方向上,水平方向不会发生折叠。
# 外边距折叠的几种情况
- 相邻的两个元素之间的外边距会折叠(除非后一个元素需要清除之前的浮动)
- 在父元素与其第一个子元素之间不存在边框、内边距、行内元素,也没有创建BFC、或者清除浮动将两者的margin-top分开,此时子元素的外边距会“溢出”到父元素外面
- 在父元素与其最后一个子元素之间不存在边框、内边距、行内元素、height、min-height、max-height将两者的margin-bottom分开,此时子元素的外边距会“溢出”到父元素外面
# 如何避免外边距叠加
- 浮动元素、inline-block元素、绝对固定定位元素的margin不会和垂直方向上其他元素的margin折叠
- 创建了块级格式化上下文的元素,不和它的子元素发生margin折叠
注:触发了BFC的元素只是与其子元素不发生margin折叠,但和其上下相邻元素的margin还是会折叠。