关于 margin ……

去很长一段时间我都觉得 margin 似乎有问题[1],因为他有些看起来怪异的特性。但直到最近才知道这并不能算是「怪异」

重叠的特性

1
2
3
<div style="margin-bottom: 20px;">20px bottom margin</div>
<div style="margin-top: 40px;">40px top margin</div>

最终这两个 div 之间的距离会是 40px,而不是 padding 那样的 60px,第二个 div 的 margin 有 20px 都跟第一个 div 重叠了。

消除重叠

其实也挺简单的,若是列表项,则只设置 margin-top/margin-bottom 其中一个就行,然后第一个/最后一个将 margin-top/margin-bottom 设置为 0 即可。或者干脆换成 padding 也可以。

或者将元素设置为 inline 也能达成消除重叠的效果

为什么有重叠

因为 margin 表示的是元素隔开的距离。当两个不同 margin 的元素放在一起,会选择 margin 值最大的。另外如果没有这种重叠效果,跟 padding 还挺像的[2]……

作为第一个或最后一个子元素的 margin 问题

这个是比较诡异的地方了。

1
2
3
4
5
6
7
8
9
10
11
12
<style>
* {
color: white;
}
</style>
<div style="background: rgb(48, 103, 133)">before</div>
<div style="background: rgb(214, 3, 17);">
<div style="margin-top: 1em;">inner-first</div>
<div style="margin-bottom: 1em;">inner-last</div>
</div>
<div style="background: rgb(48, 103, 133)">after</div>

可以看到,父元素的高度并没有被子元素的两个 margin 撑开[3],而是跑到外面去了,他们看起来变成了父元素的 margin。如果给父元素加上 margin-top: 1.2em; 会发现它们之间也有重叠的特性。

更有趣的是,若父元素设置了 border 或者 padding,它的高度就会被撑开了。


  1. 在写 Pache 的时候遇到这样的问题 ↩︎

  2. 虽然语义完全不一样,padding 表示的是内边距(俗称留白补白),而 margin 表示的是外边距(元素隔开的距离) ↩︎

  3. 父元素的 offsetHeight 没有变化。这可是一个坑…… ↩︎