外边距重叠
当块级元素的上外边距margin-top和下外边距margin-bottom同时有设定时,只会只保留最大边距,这种行为被称为边界折叠或外边距重叠。
- 在块级元素之间发生,但是不包括浮动和绝对定位
- 只发生在和当前文档流方向相垂直的方向(默认是垂直方向上)
# margin合并的3种场景
有三种情况会发生外边距重叠
- 相邻兄弟之间元素
- 父级和第一个/最后一个子元素
- 空块级元素
# 相邻兄弟之间元素
<style>
p:nth-child(1){
margin-bottom: 50px;
}
p:nth-child(2){
margin-top: 30px;
}
</style>
<p>第一行</p>
<p>第二行</p>
2
3
4
5
6
7
8
9
10
11
第一行
第二行
如果没有发生边界合并的话,两行之间的距离应该为80px,但实际效果是50px。
# 父级和第一个/最后一个子元素
此外,如果我们想要让标题固定在背景的某个位置,会利用margin-top定位来实现,让标题在垂直距离上进行调整。
案例如下所示,实际得到的效果是整个背景容器掉了下来,而标题的位置并没有改变。
Margin Collpase
问题产生的原因就是父子margin的合并,父元素的margin为0,子元素的marginTop为100px,最终的margin全部合并到了父元素上。等同于在父元素上设置margin-top的效果。
对于阻止margin合并,可以进行如下操作
阻止margin-top合并
- 父元素设置为BFC元素
- 父元素设置为border-top值
- 父元素设置为padding-top值
- 父元素和第一个子元素之间添加内联元素进行分隔
阻止margin-bottom合并
- 父元素设置为BFC元素
- 父元素设置为border-bottom值
- 父元素设置为padding-bottom值
- 父元素和最后一个子元素之间添加内联元素进行分隔
- 父元素设置height、min-height或max-height
# 空块级元素
空块级元素的margin合并
第一行,高度为27px
第二行,高度为27px
<style>
.father p {
margin: 0;
}
.demo3 .son {
margin-top: 40px;
margin-bottom: 10px;
}
</style>
<div class="father">
<p>第一行,高度为27px</p>
<div class="son"></div>
<p>第二行,高度为27px</p>
</div>
2
3
4
5
6
7
8
9
10
11
12
13
14
father的高度为94px,所以中间son元素的高度为40px,但是margin被设置为了50px,所以发生的margin合并。
如果不希望空块级元素发生margin合并,可以进行如下操作
- 设置垂直方向上的border
- 垂直方向上的padding
- 里面添加内联元素进行分隔
- 设置height或min-height
# margin合并的计算规则
margin合并的计算规则可以归纳为为“正正取大值”、“正负值相加”、“负负最负值”3
(1) 正正最大值
如果是相邻兄弟合并
<style>
.a { margin-bottom: 50px }
.b { margin-top: 20px }
</style>
<div class="a"></div>
<div class="b"></div>
2
3
4
5
6
此时a和b之间的间距为50px,取较大的那个
如果是父子合并
<style>
.father { margin-top: 20px }
.son { margin-top: 50px }
</style>
<div class="father">
<div class="som"></div>
</div>
2
3
4
5
6
7
此时父元素等同于设置了margin-top:50px
如果是自身合并
<style>
.a {
margin-top: 20px;
margin-bottom: 50px;
}
</style>
<div class="a"></div>
2
3
4
5
6
7
此时a元素的外部尺寸为50px
(2) 正负相加
如果是相邻兄弟合并
<style>
.a { margin-bottom: 50px }
.b { margin-top: -20px }
</style>
<div class="a"></div>
<div class="b"></div>
2
3
4
5
6
此时a和b之间的间距为30px,取较大的那个
如果是父子合并
<style>
.father { margin-top: -20px }
.son { margin-top: 50px }
</style>
<div class="father">
<div class="som"></div>
</div>
2
3
4
5
6
7
此时父元素等同于设置了margin-top:30px
如果是自身合并
<style>
.a {
margin-top: -20px;
margin-bottom: 50px;
}
</style>
<div class="a"></div>
2
3
4
5
6
7
此时a元素的外部尺寸为30px
(2) 负负最负值
如果是相邻兄弟合并
<style>
.a { margin-bottom: -50px }
.b { margin-top: -20px }
</style>
<div class="a"></div>
<div class="b"></div>
2
3
4
5
6
此时a和b之间的间距为-50px,取较大的那个
如果是父子合并
<style>
.father { margin-top: -20px }
.son { margin-top: -50px }
</style>
<div class="father">
<div class="som"></div>
</div>
2
3
4
5
6
7
此时父元素等同于设置了margin-top:-50px
如果是自身合并
<style>
.a {
margin-top: -20px;
margin-bottom: -50px;
}
</style>
<div class="a"></div>
2
3
4
5
6
7
此时a元素的外部尺寸为-50px
# margin合并的意义
兄弟元素之间的margin合并是为了图文信息的排版更加舒服自然。加入没有margin合并这种说法,那么连续段落或列表的首尾项间距和会其他兄弟标签之间的产生不同的间距。
父子margin合并的意义在于:在页面中任何地方嵌套或直接放入任何裸div,都不会影响原来的块状布局。div的作用就是用于分组的,从行为表现上来看,一个纯粹的div元素是不能够也不可以影响原先的布局的。
自身margin合并的意义在于可以避免不小心遗落或生成空标签影响排版和布局。