块级元素的margin-top和margin-bottom有时会发生合并
margin合并计算规则为正正取大值,正负值相加,负负最负值。
发生的条件:
- 块级元素但不包括浮动和绝对定位元素
- 只发生在垂直方向
常见的发生margin合并的场景
- 相邻兄弟元素发生合并,这也是最常见的一种。
<style type="text/css">
div{
margin-bottom: 20px;
}
p{
margin-top: 20px;
}
</style>
</head>
<body>
<div>top</div>
<p>bottom</p>
此时div和p间的高度为20px
- 父级和第一个/最后一个子元素。我们直接上例子:
<div class="father">
<div class="son" style="margin-top:80px;">
son
</div>
</div>
<div class="father" style="margin-top:80px;">
<div class="son">
son
</div>
</div>
<div class="father" style="margin-top:80px;">
<div class="son" style="margin-top:80px;">
son
</div>
</div>
可以看到它们的效果都是一样的,父元素的margin-top和第一个子元素的margin-top会发生合并,父元素的margin-bottom和最后一个子元素的margin-bttom会发生合并。在这里margin合并可以通过一下操作来阻止:
对于 margin-top 合并,可以进行如下操作(满足一个条件即可):
- 父元素设置为块状格式化上下文元素;
- 父元素设置 border-top 值;
- 父元素设置 padding-top 值;
- 父元素和第一个子元素之间添加内联元素进行分隔。
对于 margin-bottom 合并,可以进行如下操作(满足一个条件即可):
- 父元素设置为块状格式化上下文元素;
- 父元素设置 border-bottom 值;
- 父元素设置 padding-bottom 值;
- 父元素和最后一个子元素之间添加内联元素进行分隔;
- 父元素设置 height、min-height 或 max-height。
- 空元素的margin合并
空块级元素的 margin 合并。例如,下面 CSS 和 HTML 代码:
.father { overflow: hidden; }
.son { margin: 1em 0; }
<div class="father">
<div class="son"></div>
</div>
结果,此时.father 所在的这个父级div元素高度仅仅是 1em,因为.son 这个空div元素的 margin-top 和 margin-bottom 合并在一起了。这也是上一节 margin:50%最终宽高比是 2:1 的原因,因为垂直方向的上下 margin 值合二为一了,所以垂直方向的外部尺寸只有水平方向的一半。这种空块级元素的 margin 合并特性即使自身没有设置 margin 也是会发生的,所谓“合”并不一定要自己出力,只要出人就可以。比方说,我们一开始的“相邻兄弟元素 margin 合并”,其实,就算兄弟不相邻,也是可以发生合并的,前提是中间插手的也是个会合并的家伙。比方说:
p { margin: 1em 0; }
<p>第一行</p>
<div></div>
<p>第二行</p>
此时第一行和第二行之间的距离还是 1em,中间看上去隔了一个div元素,但对最终效果却没有任何影响。如果非要细究,则实际上这里发生了 3 次 margin 合并,div和第一行p的 margin-bottom 合并,然后和第二行p的 margin-top 合并,这两次合并是相邻兄弟合并。由于自身是空div,于是前两次合并的 margin-bottom 和 margin-top 再次合并,这次合并是空块级元素合并,于是最终间距还是 1em。
以上部分内容来自张鑫旭的《CSS世界》