1. BFC (Block formatting contexts)
在BFC中,盒子从顶端开始垂直地一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin 值所决定的。在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。
以下这些元素,会为他们的内容创建新的 BFC。
- 浮动元素
- 绝对定位元素
- 非块级盒子的块级容器(如
inline-blocks
,table-cells
, 和table-captions
)overflow
值不为“visiable
”的块级盒子
2. margin 的折叠
在 CSS 中,相邻的两个盒子(可能是兄弟关系,可能是父子关系)的外边距可以合并为一个单独的外边距,即外边距的折叠。
要求:
- 处于常规文档流的块级盒子,且处于同一个
BFC
中。 - 没有线盒,没有空隙,没有
padding
和border
将他们分隔开。 - 都属于垂直方向上相邻的外边距。
效果:
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 两个外边距一正一负时,折叠结果是两者的相加的和。
例子一:正常文档流中折叠外边距
.orange {
background: orange;
width: 100px;
height: 100px;
margin: 10px;
}
.purple {
background: purple;
width: 200px;
height: 200px;
margin: 20px;
}
.gray {
background: gray;
width: 100px;
height: 100px;
margin: 20px;
}
<div class="orange"></div>
<div class="purple"></div>
<div class="grey"></div>
例子二:元素块之间有 border
隔离时 margin
不折叠
给上面的 CSS 加如下样式:
.wrap {
border: 1px solid black;
}
<div>
<div class="wrap">
<div class="orange"></div>
</div>
<div class="wrap">
<div class="purple"></div>
</div>
<div class="wrap">
<div class="gray"></div>
</div>
</div>
3. 浮动和绝对定位不与任何元素产生 margin 折叠
因为元素会脱离文档流,会创建一个新的BFC。
但是浮动元素脱离了当前的BFC并不影响它后面的兄弟元素,后面的兄弟元素与浮动元素前面的元素依然在同一个BFC当中,所以,它们之间的margin还是会折叠的。
例子三:浮动元素不影响同一个BFC 里的元素 margin 折叠
.wrapper {
width: 500px;
height: 450px;
border: 1px solid red;
}
.big-box {
width: 120px;
height: 120px;
margin: 20px;
background: #1E90FF;
}
.middle-box {
width: 100px;
height: 100px;
margin: 30px;
background: #ffcf14;
}
.small-box {
width: 100px;
height: 50px;
margin: 10px;
background: #8bc528;
}
.floatL {
float: left;
}
.clear {
clear: both;
}
<div class="wrapper">
<div class="big-box">one non-float</div>
<div class="middle-box floatL">
two float-left
</div>
<div class="small-box">three non-clear-float</div>
</div>
例子四:有空隙(clearance)时,会阻止外边距合并
什么时候会产生空隙?
清除浮动的元素(即设置了 clear 属性的元素) ,会在元素上外边距之上增加清除空间,而外边距本身并不改变。
该空隙会阻止元素margin-top的折叠,并作为间距存在于元素的margin-top的上方。
如果清除绿色块周围的浮动,将绿色块的 html
改为:
<div class="small-box clear">three clear-float</div>
效果如下:
4. inline-block元素与其兄弟元素、子元素和父元素的外边距都不会折叠(包括其父元素和子元素)
因为块级盒子的display属性必须是以下三种之一:block
, list-item
, 和 table
。