合并margin
CSS中,两个或多个盒(可能但不一定是兄弟)的相邻的margin会被结合成一个margin。外边距按这种方式结合叫做合并(collapse),产生的结合的外边距叫做折叠外边距
计算规则
当两个或者更多的margin合并时,产生的margin宽度为合并margin宽度中的最大值。至于负margin,就从正相邻margin的最大值中减去负相邻margin的绝对值的最大值。如果没有正margin,就用0减去相邻margin的绝对值的最大值
合并规则
根据 CSS2.1规范,可以知道以下:
-
相邻的垂直外边距会合并,除了:
- 根元素盒的margin不合并
- 如果一个带有间隙(指clear属性导致元素位置移动形成的间隙)的元素的上外边距与下外边距相邻,它的外边距会和紧挨着的兄弟(元素)的相邻外边距合并,但合并后不会再和父级块的下外边距合并
-
水平margin不会合并
-
两个margin是 相邻的 ,当且仅当:
- 都属于流内(in-flow)块级盒,处于同一个块格式化上下文
- 没有行框(line box),空隙,内边距和边框把它们隔开(注意,因此某些0高度行框会被忽略)
- 都属于垂直相邻框边界,即形成下列某一对:
- 盒的上边距与其第一个流内孩子的上边距
- 盒的下边距与其下一个流内紧挨着的兄弟的上边距
- 最后一个流内孩子的下边距与其height计算值为’auto’的父元素的下边距
- 盒的上边距和下边距,要求该盒没有建立新的块格式化上下文,并且’min-height’计算值为0,‘height’计算值为0或’auto’,还没有流内孩子
margin相邻现象举例说明
1.当两个盒子都属于流内(处于普通文档流内)块级盒,处于同一个块格式化上下文(BFC)。
由此可知,
- 处于不同BFC的两个盒子的margin不相邻(即可知,可以通过将盒子分别分离到不同BFC中去避免其出现margin重叠现象)
- 且BFC元素和它的子元素不会发生margin重叠(因为它们处于不同BFC中)
例1,设置div的样式如下,其中margin为20px,可以从图中看出,由于两个div属于流内,且处于同一个BFC中,通过选中可以看出两个div发生margin重叠,两个div之间的间距为20px。
div {
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
<div></div>
<div></div>
当元素脱离文档流时,不会发生margin重叠,如下:
div {
width: 100px;
height: 100px;
background: red;
margin: 20px;
float: left;
}
<div></div>
<div></div>
<div></div>
<div></div>
当元素处于不同BFC时,不会发生margin重叠,如下:
.content {
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.bfc {
overflow: hidden;
}
<div class="bfc">
<div class="content"></div>
</div>
<!--两个content处于不同BFC中-->
<div class="content"></div>
例2.当父、子元素都是流内元素,且属于同意BFC时,出现margin重叠(father到根元素的margin最终为son的30px)
.father {
width: 100px;
height: 100px;
background: red;
margin: 20px;
}
.son {
width: 50px;
height: 50px;
background: yellow;
margin: 30px;
}
<div class="father">
<div class="son"></div>
</div>
当设置父元素father设置为脱离文档流时,可以看出,father和son没有出现margin重叠现象
.father {
width: 100px;
height: 100px;
background: red;
margin: 20px;
float: left;
}
由于设置float和定位就等于将father变成了BFC,即就让father和son处于了不同BFC中,结果和上述一样,这里就不在赘述了。
2.没有行框(line box),空隙,内边距和边框把它们隔开
意思就是说,两个margin之间接触,中间没有其他东西,就会出现重叠。
例3,父元素设置border,就可以看到父子元素之间没有出现margin重叠
例4,当一个元素设置了margin,但是该元素高度为0时,也会出现margin重叠,如下
.targ {
width: 100px;
height: 0;
margin: 20px;
}
.sbling{
width: 50px;
height: 50px;
background: yellow;
}
<div class="targ"></div>
<div class="sbling"></div>
当设置了padding时,就不会了,如下:
3. 最后一个流内孩子的下边距与其height计算值为’auto’的父元素的下边距,即当父元素的高度为auto时,其marginbottom和其最后一个流内子元素的marginbottom会合并。
例5,father的高度为auto,它和它的最后一个流内孩子son的下边距重叠,最后father和sibling之间的间距为150px,如下
.father {
width: 100px;
margin-bottom: 100px;
}
.son {
width: 100px;
height: 100px;
margin-bottom: 150px;
background: red;
}
.sibling {
width: 100px;
height: 100px;
background: yellow;
}
<div class="father">
<div class="son"></div>
</div>
<div class="sibling"></div>
当给father设置height之后发现,此时sibling与father的垂直距离,只跟它们的margin值有关,与child的margin值无关,如下:
当给father设置padding、border之后,可以发现father的高度被自动撑开为250px,此时它与sibling之间的距离也只受他们之间margin值的影响,如下:
4.盒的上边距和下边距,要求该盒没有建立新的块格式化上下文,并且’min-height’计算值为0,‘height’计算值为0或’auto’,还没有流内孩子
例6,content没有建立新的BFC,且高度为0,并且没有流内孩子,其与sibling的间距为100px,即其上下边距发生了合并
.content {
width: 100px;
height: 0px;
margin: 100px;
}
.sibling {
width: 100px;
height: 100px;
background: yellow;
}
<div class="content">
</div>
<div class="sibling"></div>
当设置content为BFC后(设置padding、border、height同样),间距为200px,如下,
总结
只要两个margin之间被“隔开”了,包括被分离到不同BFC和被border、padding、高度、空隙或者其他内容隔开,就不会发生margin合并
以下摘自 CSS2.1规范
- 浮动的盒与任何其它盒之间的margin不会合并(甚至一个浮动盒与它的流内子级之间也不会)
- 建立了新的块格式化上下文的元素(例如,浮动盒与’overflow’不为’visible’的元素)的margin不会与它们的流内孩子合并
- 绝对定位的盒的margin不会合并(甚至与它们的流内子级也不会)
- inline-block盒的margin不会合并(甚至与它们的流内子级也不会)
- 流内块级元素的bottom margin总会与它的下一个流内块级兄弟的top margin合并,除非该兄弟(元素)具有间隙
- 流内块级元素的top margin会与它的第一个流内块级子级的top margin合并,条件是该元素没有上边框和上内边距,并且其孩子不具有间隙
- 一个’height’为’auto’并且’min-height’为0的流内块级盒的bottom margin会与它的最后- - 一个流内块级子级的bottom margin合并,条件是该盒没有下内边距和下边框,并且其孩子的下外边距没有与具有间隙的上外边距合并
- 盒自身的外边距也会合并,条件是’min-height’属性为0,既没有上下边框,也没有上下内边距,‘height’为0或’auto’,且不含行框的话,那么其所有流内孩子的外边距(如果存在的话)都会合并