合并外边距
CSS中,两个或多个盒(可能但不一定是兄弟)的相邻的垂直方向的margin会被结合成一个margin。外边距按这种方式结合叫做合并(collapse)
1、相邻的垂直外边距会合并,除了
- html和body的外边距不合并
- 元素如果带有clear属性(生成间隙clearance),上外边距与下外边距相邻(height为0),那么它的外边距会和兄弟的相邻外边距合并,但合并后的margin不会再和父级的下外边距合并。下面是例子:
没有clear属性产生的clearance时:
<style>
*{
margin:0;
}
.container{
margin: 50px;
background: pink;
}
.container>div{
width: 100px;
height: 100px;
text-align: center;
line-height: 100px;
color:aqua;
font-size: 20px;
}
.top{
background-color: red;
margin: 50px;
}
div.middle{
width: 200px;
height: 200px;
margin: 50px;
background-color: green;
}
.bottom{
background-color: yellow;
margin: 100px;
height: 0 !important;
}
</style>
<div class="container">
<div class="top">top</div>
<div class="middle">middle</div>
<div class="bottom"></div>
</div>
效果:
标注分析:
ps:如果bottom框有文字内容,那么就会引入行框(line box)(即bottom框的上下外边距不相邻),则bottom框的margin-top就不会和父容器的margin-bottom合并。如果bottom框建立新的块格式化上下文(例如display:flex)则同样不合并。
有clearance时:
div.middle{
width: 200px;
height: 200px;
margin: 50px;
+float: left; //middle加上浮动
background-color: green;
}
.bottom{
background-color: yellow;
margin: 100px;
height: 0 !important;
+clear: left; //bottom加上清除浮动,形成间隙
}
效果:
标注分析:
2、两个margin是相邻的,当且仅当:
-
都属于文档流内(in-flow)块级盒(display为block、list-item或者table的),处于同一个块格式化上下文
-
没有行框(line box),空隙,内边距和边框把它们隔开(注意,因此某些0高度行框会被忽略)
-
都属于垂直相邻框边界(vertically-adjacent box edges),即形成下列某一对:
父子盒子外边距相邻:- 盒的上边距与其第一个流内(in-flow)孩子的上边距
- 最后一个流内孩子的下边距与其height计算值为’auto’的父元素的下边距
相邻兄弟盒子外边距相邻:
- 盒的下边距与其下一个流内紧挨着的兄弟的上边距
盒子自身的上下外边距相邻:
要求高度为0,并且没有建立新的块格式化上下文
3、注意
- 相邻外边距也可以由不具兄弟或祖先关系的元素生成;例如图三的例子中,如果外部容器后面再跟一个块,那么这个新盒子的上外边距会和之前已经合并了的三个margin再次合并,形成四margin合并。
- 浮动盒子不会和其他盒margin合并(包括它本身流内子级)
- 建立了新的块级格式化上下文的盒子的上下margin不会和它的内流子级合并
4、合并后的外边距计算
两个或多个外边距合并时:
- 正值margin:取最大
- 负值margin:Math.max(正margins || 0 )- Math.max( Math.abs(负margins))
当涉及到上下外边距相邻的盒子
- 如果该元素的外边距与其父元素的上外边距合并了,盒的上边框边界被定义为与其父元素的相同(父子元素margin-top合并时逃不出父盒子的content)
- 外边距合并时可能会穿过它被折叠外边距,穿过的元素的位置不影响其它外边距正要被合并的元素的位置,其上边框边界的位置仅用于布局这些元素的后代元素