8.8 相邻兄弟的margin折叠与避免
8.8.1 规则详情
(1)规则描述:同一BFC内,兄弟两个元素垂直方向margin进行折叠。
(2)详情描述:无论上方或下方元素是否存在相关padding或border,上方元素margin-bottom与下方元素margin-top总是相邻,所以设置padding与border无法避免折叠。
8.8.2 不合理的折叠示例
页面初始代码。设置div1的margin-bottom为20px,div2的margin-top为 20px,期望总间距40px。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
.div1{
background-color: #0aaa76;
width: 200px;
height: 30px;
margin-bottom: 20px;
}
.div2{
background-color: #4aa6fc;
width: 200px;
height: 30px;
margin-top: 20px;
}
</style>
</head>
<body>
<div class="div1">
小步教程
</div>
<div class="div2">
xiaobuteach.com
</div>
</div>
</body>
</html>
期望效果
实际结果不符合期望
8.8.3 兄弟margin折叠的本质
兄弟margin-top折叠之BFC示意图
同一BFC内,兄元素margin-bottom与弟元素margin-top相邻。
8.8.4 BFC避免折叠
(1)在兄与弟内部同时新建BFC,也无法避免折叠。BFC示意图如下。
即使两者都在内部新建BFC,兄div的margin-bottom与弟div的margin-top仍属于BFC-X,仍然相邻。此方法无效。
(2)直接设置双方padding或border也无效,盒子示意图如下,两者始终相邻。
(3)间接解决方法。其中一个div再添加父元素,父元素设置新建BFC,即避免两个margin在同一BFC。原先的两个兄弟元素最终已经不是兄弟。
绿色实线表示弟div添加的父div,虚线表示它内部新建的BFC对象。两个元素的margin区域不在同一个BFC。
完整代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>小步教程</title>
<style>
.div1{
background-color: #0aaa76;
width: 200px;
height: 30px;
margin-bottom: 20px;
}
.div2{
background-color: #4aa6fc;
width: 200px;
height: 30px;
margin-top: 20px;
}
.div2-wrap{
display: flow-root;
}
</style>
</head>
<body>
<div class="div1">
小步教程
</div>
<div class="div2-wrap">
<div class="div2">
www.xiaobuteach.com
</div>
</div>
</div>
</body>
</html>
div2-wrap内部新建BFC,实现期望效果。同理可以在div1外加div1-wrap并新建BFC。
8.8.5 多重margin折叠
上述代码取消div2-wrap的flow-root设置,运行结果仍然发生折叠。因为发生多重margin折叠:第1次折叠,div2的margin穿透到div2-wrap,这是父子折叠;第2次折叠,上步产生的margin区域又与div1发生兄弟折叠。所以仍然无法避免折叠。
示例代码
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>margin折叠 | 小步教程</title>
<style>
body {
margin: 0;
}
.div1 {
border-bottom: 1px solid #666;
}
.div2-wrap {
margin-top: 20px;
background-color: #999;
width: 300px;
}
.div2 {
margin-top: 20px;
background-color: #0aaa76;
width: 250px;
}
.div2-1 {
margin-top: 30px;
background-color: #4aa6fc;
height: 30px;
margin-left: 20px;
}
.div2-2 {
margin-top: 20px;
background-color: #ed7d31;
height: 30px;
margin-left: 20px;
}
.div3 {
border-top: 1px solid #666;
}
</style>
</head>
<body>
<div class="div1">div1</div>
<div class="div2-wrap">
<div class="div2">
<div class="div2-1">div2-1 小步教程</div>
<div class="div2-2">div2-2 xiaobuteach.com</div>
</div>
</div>
<div class="div3">div3</div>
</body>
</html>
运行结果
元素div2-1的margin-top穿透父元素div2,并穿透其爷元素div2-wrap。
8.8.6 非新建BFC方法参考
下列方法根据具体需求场景选择使用。
方法1:合理运用折叠,合理设置margin值,实现目标效果。
方法2:直接合并margin值。相邻兄弟只设置一个元素的margin值,避免margin相邻。
方法3:改设padding值。padding值不会发生重叠。