8.5 margin折叠的合理性

8.5.1 兄弟折叠的合理性示例

初始场景。段落p1与上下div的垂直margin值20px,效果如下。

img

初始代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小步教程</title>
    <style>
        div{
            background-color: #4aa6fc;
        }
        p{
            margin: 20px 0 ;
            background-color: #0aaa76;
        }
    </style>
</head>
<body>
    <div class="div1">div1</div>
    <p class="p1">p1 小步教程 xiaobuteach.com</p>
    <!-- <p class="p2">p2 小步教程 xiaobuteach.com</p> -->
    <div class="div2">div2</div>
</body>
</html>

新需求。p1后面加入p2,关键问题:期望p1与p2之间的margin间距是多少?

第1种设计:希望p1与p2之间的margin间距是40px。

img


第2种设计:希望p1与p2之间的margin间距仍然是20px。

img

第2种设计更符合当前场景,段落之间的间距仍然保持20px。所以,BFC模型设计自动的兄弟margin折叠,页面渲染时两者之间的margin折叠成20px。测试一致。


开发者工具识别兄弟margin折叠。分别选择p1与p2元素,查看盒子的页面显示,合并图如下。

img

如桔色区域所示,p1的margin-bottom与p2的margin-top区域完全重合。


8.5.2 父子折叠的合理性示例

初始页面场景。div2与上下div的垂直margin间距是20px,效果如下。

img

初始代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小步教程</title>
    <style>
        div {
            background-color: #4aa6fc;
        }

        .div2 {
            margin: 20px 0;
        }
    </style>
</head>

<body>
    <div class="div1">div1</div>
    <div class="div2">        
        div2 小步教程 xiaobuteach.com        
    </div>

    <div class="div3">div3</div>
</body>
</html>

新需求。div2内部替换成新的元素p1,p1本身也有设置margin-top,关键问题:期望div2与div1之间margin间距是多少?期望p1与div2上方margin间距是多少?

示例代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小步教程</title>
    <style>
        div {
            background-color: #4aa6fc;
        }

        .div2 {
            margin: 20px 0;
        }

        p {
            margin: 20px 0;
            background-color: #0aaa76;
        }
    </style>
</head>

<body>
    <div class="div1">div1</div>
    <div class="div2">
        <p class="p1">p1 小步教程 xiaobuteach.com</p>
    </div>

    <div class="div3">div3</div>
</body>
</html>

第1种设计:期望按照原始计算,分别是20px、20px。

img


第2种设计:期望尽量减少间距,对margin进行合并,p1显示在div1顶部。

img

第2种设计更符合当前场景,所以BFC模型设计了自动的父子margin折叠。测试一致。


开发者工具识别父子margin折叠。分别查看div2与p1,合并图如下。

img

如桔色区域所示,两者margin区域完全重合。


8.5.3 随处可见的margin折叠

浏览器为标签设置默认样式,即使没有手动设置任何样式,也经常发生margin重叠。

示例代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>小步教程</title>

</head>

<body>
    <h3>小步教程 xiaobuteach.com</h3>
    <p>小步教程 xiaobuteach.com</p>
</body>
</html>

body默认margin: 8px,h3默认margin绝对值18.72px 0,p默认margin绝对值16px 0。

分别选中body,h3,p元素,查看盒子的页面显示。

img

(1)body与h3的margin-top发生折叠,属于相邻父子折叠,而且body的margin-top被穿透(即子元素的margin-top超出父元素的margin-top)。

(2)h3的margin-bottom与p的margin-top发生折叠,属于相邻兄弟折叠。

(3)body与p的margin-bottom发生折叠,而且body的margin-bottom被穿透。

这些折叠具有合理性。也存在一些需求场景,不需要折叠,只想按原始方式计算与显示。