CSS盒模型中有一个概念叫做外边距(margin),用来设置对象四边的外延边距。但是对于位置上存在边距相遇(相邻、包含、自身为空)的元素,有时候会发生垂直方向上的margin合并的情景。
准则
- 外边距合并指的是,当两个垂直外边距相遇时(一定是直接相遇而没有padding或者border的阻隔),它们将合并形成一个外边距
- 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者
- 如果出现负值,分为一正已负、两个全是负
常见形式
- 两元素相邻时

- 两元素存在包含关系时

注意,此时的合并的边距指的是外部元素的边距,而不是两者相接触的内部边距。w3cSchool描述有误。
- 自身为空元素时(chrome证实不会发生合并)
假设有一个空元素,它有外边距,但是没有边框或填充。在这种情况下,上外边距与下外边距就碰到了一起,它们会发生合并

以上是w3cSchool中的描述,经过验证并不存在。
总结
经过上面实例,现可总结如下:
- 对于两个相邻(标签嵌套属于同一层级)元素,由于没有任何阻隔,所以外边距必定会相遇,相遇时边距合并遵循谁大以谁为准的原则
- 对于父子嵌套元素,如果任何一者声明了border或者padding,那么margin被阻隔,便不会发生合并。如果没有阻隔,那么他们中的较大的margin值成为父元素的外边距实际值,而内部子元素针对于父元素的margin值消失
- 对于一个没有border、padding、content的元素,margin正常,不会发生自身合并
- 只有普通文档流中块框的垂直外边距才会发生外边距合并。行内框、浮动框或绝对定位之间的外边距不会合并。
意义和影响
如下,是w3cSchool中的描述,但是对应到上面的验证和总结,其实这是错误的。错在外部元素包裹内部元素时,第一个内部元素的margin值被合并到外部元素的margin中,因此表现出来就像没有设置margin一样。

实际表现如下(chrome):
<div class="wrap">
<div class="outer-container">
<p class="paragraph">段落1</p>
<p class="paragraph">段落2</p>
<p class="paragraph">段落3</p>
<p class="paragraph">段落4</p>
</div>
</div>
.outer-container {
background: red;
}
.paragraph {
width: 100px;
background-color: yellow;
margin: 10px auto;
}

一定注意:对于嵌套元素,第一个正常文档流的上边距一定会被父元素吞并当做自己的边距。就像子元素没有设置上外边距一样。不论嵌套了几层。