什么是外边距重叠(margin collapsing)?重叠的结果是什么?如何解决?
两个或多个毗邻的普通流中的块元素垂直方向上的 margin 会折叠。
1. 两个或多个
说明其数量必须是大于一个,又说明折叠是元素与元素间相互的行为,不存在 A 和 B 折叠、B 没有和 A 折叠的现象。
2. 毗邻
是指没有被非空内容、padding、border 或 clear 分隔开,说明其位置关系。
注意一点:在没有被分隔开的情况下,一个元素的 margin-top 会和它普通流中的第一个子元素(非浮动元素等)的 margin-top 相邻;只有在一个元素的 height 是 "auto" 的情况下,它的 margin-bottom 才会和它普通流中的最后一个子元素(非浮动元素等)的 margin-bottom 相邻。
3. 垂直方向
是指具体的方位,只有垂直方向的 margin 才会折叠,水平方向的 margin 不会发生折叠。
4. 折叠计算规则
- 两个相邻的外边距都是正数时,折叠结果是它们两者之间较大的值。
- 两个相邻的外边距都是负数时,折叠结果是两者绝对值的较大值。
- 两个外边距一正一负时,折叠结果是两者的相加的和。
5. 如何解决外边距重叠?
<div style="width:100px; background:#930; height:100px; margin-bottom:10px;"></div>
<div style="width:100px; background:#f30; height:100px; margin-top:10px;"></div>
如果触发上下 <div> 元素的 BFC,是无法避免 margin 折叠的——这与很多人的直觉相反。
6. 真正使上下 margin 不折叠的方法
- 浮动元素、inline-block 元素、绝对定位元素的 margin 不会和垂直方向上其他元素的 margin 折叠(注意这里指的是上下相邻的元素)。
- 创建了块级格式化上下文(BFC)的元素,不和它的子元素发生 margin 折叠(注意这里指的是创建了 BFC 的元素和它的子元素)。
触发 BFC 的因素:float(除了 none)、overflow(除了 visible)、display(table-cell / table-caption / inline-block)、position(除了 static / relative)。
补充:
- 相邻元素不发生折叠的因素是触发 BFC 因素的 子集——如果为上下相邻的元素设置
overflow: hidden,虽然触发了 BFC,但上下元素的上下 margin 还是会发生折叠。- BFC 不是万能的,它只是让元素本身能正确计算宽高,并不能阻止相邻兄弟元素的 margin 折叠。
- 实战建议:写代码时尽量统一方向(如全部使用
margin-top或margin-bottom),避免一正一负叠加造成意想不到的间距。



