collapse-margin

What the FUCK is Collapsing margins

外边距折叠。

一 、发生该现象的表现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<div class="case collapse">
<div class="one">子一</div>
<div class="two">子二</div>
</div>
<hr>
<div class="case noCollapse">
<div class="one">子一</div>
<div class="two">子二</div>
</div>
<style>
.case { width:200px; background-color:yellow; }
.one {background-color:teal;margin-top:20px}
.two {background-color:olive;}
.noCollapse {padding-top:0.01px}
</style>

图1
上图中两个case初始时是一样的。我们给div.one设置了一个margin-top,本意应该是使其与父元素的的border-top有20px的间隙,故应该露出20px父元素div.case的背景色yellow(如第二个case),但是第一个case却没有出现,表现的却是好像和父元素case的上边一起有了一个margin-top 20px的效果。两个case区别只是第二个case多了一个padding-top

再看一个栗子:

1
2
3
4
5
6
7
还是上面的html结构,改下部分css
.collapse .one {margin-bottom:25px;}
.collapse .two {margin-top:20px;}
.noCollapse {overflow: auto;}
.noCollapse > div {float:left;}
.noCollapse > .one {margin-right:20px;}
.noCollapse > .two {margin-left:20px;}

图2
上图中case1下的两个div间距为25px,case1中取了one的margin-bottom和two的margin-top中的一个较大的值25px,并没有取两者之和。而case2下的两个div间距为40px,取了两者之和。区别嘛,case1是垂直方向上相邻的,case2是水平方向上相邻的(浮动)。

再来:

1
2
3
4
5
还是上面的html结构,再改下部分css
.two {margin-bottom:20px}
.noCollapse {
border:1px solid;
}

图3
上图中的case2表现出了我们设置div.two元素margin-bottom的本意,即与父元素之间有一个20px的间距,而case1中却没有出现,表现的像是父元素的下边和div.two下面一起有了一个margin-bottom的效果

最后一个栗子,Google了下(百度真心不给力),看官自行考虑。这个例子是clearance对collapse的影响,下面的条件中会说明。

上面几种情况中第一个case出现的问题,就叫Collapsing margins(IE7及以下版本的的haslyout属性不符合W3C规范,不会出现这种情况)。

二、产生该现象的条件

W3C官网文档是这么解释的

  • 垂直相邻的两条边界(兄弟元素)会发生collapse,如图2,除了两种例外:
    一、根元素不参与collapse;
    二、最后一个栗子情况,其中一个元素引入了clearance间隙时不会出现collapse。间隙的解释大概是与浮动元素相邻的元素设置了不为none的clear属性时,就有可能引入间隙。有可能?上面 stackoverflow上解释了clear不为none时引和没引入clearance的两种情况。

  • 垂直相邻的两条边界(父子关系)有可能发生collapse。父元素的上边界和子元素的上边界相邻,或者父元素的下边界和子元素的下边界相邻。如图1图3情况。发生前提是:

    1
    2
    1,都属于块级元素且不包含浮动元素、绝对定位元素
    2,没有明确的边线、间隙(clearance)、padding和border。

三、解决该情况的方法

其实在产生条件那块就已经给出了解决方法,解决父子关系时产生的问题:

1
给父元素(子元素是不行的)的相邻边界加一个明确的border或者padding,明确的border包括border-width和border-style,

解决兄弟关系时产生的问题:

1
2
在同一个Block Formatting Contexts(BFC)以内的兄弟元素才会发生Collapsing,所以兄弟关系Collapsing时给他们其中之一加个父元素,然后使该父元素产生BFC,这样兄弟元素就不在是兄弟...且不会发生collapsing了
如果产生BFC及BFC是什么请参考Block Formatting Contexts这一章节

四、兄弟元素的collapse间距表现

垂直相邻的两条边界(兄弟元素)之间的间距(margin)值如下:

1
2
3
1,当margin都为正数时,取其中较大的margin为实际间距。
2,都为负数时,取绝对值大的那个负数为实际间距。
3,一正一负时,取两者的和为实际的间距

最后说下我对最后一个栗子(S.O.上的问题)的理解,准确性就有待商榷了:

1
2
3
4
5
6
7
1,case1中由于container设置了border-padding,所以div.intro是无法与container上边界collapse的,但是是有可能与下边界collapse的。
2,clear不为none时引入了clearance,使div.intro与case的下底边无法collapse,此时div.intro和case的上下边都没有collapse,故撑开了父元素container,出现了lightblue的背景色,如case2.
3,case1中div.intro原本引入了clearance,但是设置的margin-top足够大导致引入的clearance消失,使得div.intro与container下边界collapse,合并到了一起,故没有撑开container,故没有出现container的背景色lightblue。
4,关于这个clearance...大致意思是设置clear不为none时,会使得元素(兄弟元素为float时)的上边低于float元素的下边,即使元素本身下移,此时就产生了所谓的clearance。。。

最后的最后,把相关的资料放下面,自行意淫,W3C文档保平安。
collapse margin
clearance
clearance对collapse的影响
clear