Collapsing margins——合并的外边距

原文地址:https://geekplux.com/2014/03/14/collapsing_margins

昨天在写 CSS 时遇到一个小问题,困扰了我好长时间,最后 Google 之,发现早有前人踩过此坑。为免以后再掉进坑,记下来比较好。

昨天遇到的问题是这样的。我设置了一对父子元素如下:

<div class="parent">Parent <div class="children">Children </div> </div> <div class="divider"></div>

它们的样式如下:

.parent { margin-bottom: 10px; width: 80px; height: 20px; background-color: yellow; } .children { margin-bottom: 20px; width: 80px; height: 20px; background-color: red; } .divider { height: 1px; background-color: black; }

产生的效果如图所示:

为什么分割线跑到了 Children 里面?这两个父子元素都设置了 margin-bottom,加起来应该是 30px,为什么现在成了 20px?种种疑问在我脑中盘旋。刚开始以为是万恶的 position,但是我把所有能想到的属性排列组合都设置了一遍,发现还是不行。果断 Google,才知道这个问题由来已久……

collapsed margin

关于 collapsing-margin,有 W3C 的官方介绍

In CSS, the adjoining margins of two or more boxes (which might or might not be siblings) can combine to form a single margin. Margins that combine this way are said to collapse, and the resulting combined margin is called a collapsed margin.

在 CSS 中,两个或多个毗邻(父子元素或兄弟元素)的普通流中的块元素垂直方向上的 margin 会发生叠加。这种方式形成的外边距即可称为外边距叠加(collapsed margin)。

好吧,这下理解了,原来 挨着的、且没有任何东西分割的 两个普通元素会在垂直方向上合并 margin。我们可以想象出有 4 种情况会发生合并,看图比较直观(图来自网络):

到底怎么才算毗邻,其实官网对于毗邻作了很详细的解释(保证你看完会晕):

首先是一个大前提:元素之间没有被非空内容、padding、border 或 clear 分隔开。然后有下面几种情况算是毗邻:

一个元素的 margin-top 和它的第一个子元素的 margin-top
普通流中一个元素的 margtin-bottom 和它的紧邻的兄弟元素的的 margin-top
一个元素( height 为 auto )的 margin-bottom 和它的最后一个子元素的margin-bottom
一个没有创建 BFC、没有子元素、height 为0的元素自身的 margin-top 和 margin-bottom

不管你晕不晕,反正我晕了……

如何避免

避免外边距叠加,只要破坏它的 4 个必要条件(2 个或多个、毗邻、垂直方向、普通流)中的一个即可。下面是官网不构成外边距叠加的各种情况。

同样会看晕,总结下来,我们最好的办法是

整个问题解决下来,我感觉其实并没有那么复杂的东西却被文档表述的很复杂,也可能是我英语比较差。而且在开发过程中许多细节我认为没必要去抠它,只要遇到时能迅速定位出原因(我昨天遇到这个问题,第一时间就无法定位,不停换关键词去搜才慢慢明白,还是经验少啊),就可以依靠 Google 搜索出解决方案,这样可以保证开发效率。如果想深入了解,还是抽业余时间吧……下面的文章可供参考(如怎么计算 margin 的最终值)。网上的资源太丰富了,感谢这些前辈。


CC BY-NC 4.0 © GeekPluxFeeds (RSS)