背景

当对页面中元素设置 margin-top 样式时,如果该元素有父元素,则 margin-top 会应用与父元素,子元素的 top 与父元素的 top 重叠。举例说明

<style>
    body{
        margin:0; 
        padding:0;
    }
    .outerdiv{
        background: #333;
    }
    .innerdiv{
        margin-top: 30px;
        background: #d33; 
        height: 80px;
    }
</style>
<div class="outerdiv">
    <div class="innerdiv"></div>
</div>

代码如上,显示效果并非预期想象的那样。

原因分析

先看一看 CSS 中对 margin 的定义:

围绕在元素边框的空白区域是外边距。设置外边距会在元素外创建额外的 空白。 设置外边距的最简单的方法就是使用 margin 属性,这个属性接受任何长度单位、百分数值甚至负值。

这里并没提到为什么会出现这个问题,我们再往下看 外边距合并 这一节。

  • 外边距合并指的是,当两个垂直外边距相遇时,它们将形成一个外边距。
  • 合并后的外边距的高度等于两个发生合并的外边距的高度中的较大者。
  • 当一个元素出现在另一个元素上面时,第一个元素的下外边距与第二个元素的上外边距会发生合并。
  • 当一个元素包含在另一个元素中时(假设没有内边距或边框把外边距分隔开),它们的上和/或下外边距也会发生合并。
  • 外边距甚至可以与自身发生合并

到这里,我们的问题就找到了,注意上面第四条:当一个元素包含在另一个元素中时(假设没有内边距或边框把外边距分隔开),它们的上和/或下外边距也会发生合并。

没有内边距或边框把两个元素的外边距分隔开 时,外边距就会合并。拿我们刚才的例子来讲,outerdiv 和 innerdiv 正好就是这种情况,所以 innerdiv 的外边距就与 outediv 的外边距合并了。

解决

我们只要把两个外边距隔开就可以了,把两个外边距分开的方法很多,简单列举几个

  • 为父元素设置padding
  • 为父元素或子元素设置border
  • 在子元素前加入一个不是空的元素
  • 为父元素或子元素声明浮动 flat:left
  • 为父元素或子元素声明绝对定位
  • 为父元素应用overflow:hidden属性