Contents

Margin的塌陷、合并及BFC

前言

在标准文档流中,如果两个竖直方向的margin直接接触,中间没有border、padding或者content隔开就会发生margin合并、或者margin塌陷现象。

而发生两个竖直方向的margin直接接触通常有两种情况:

  1. 父子关系的块级元素。(margin塌陷)
  2. 兄弟关系的块级元素。(margin合并)

margin塌陷

margin塌陷现象通常出现在嵌套关系(父子关系)的块级元素。父元素与子元素的margin-top直接接触,这时如果给子元素设置一个margin-top,会发现父元素也跟着下来了。

代码如下:

<body style="background: grey;">
  <div style="height: 500px;background: blue;">
    <div style="height: 200px;background: green;margin-top:50px;"></div>
  </div>
</body>

效果如下:

/images/image-20210627203704822.png

margin合并

margin合并现象通常出现在兄弟关系的块级元素。两个兄弟元素的margin-bottom与margin-top直接接触,这时候会取较大的margin。

代码如下:

<body style="background: grey;">
  <div style="height: 500px;background: blue;">
    <div style="height: 200px;background: green;margin-bottom: 10px;"></div>
    <div style="height: 200px;background: green;margin-top:50px;"></div>
  </div>
</body>

效果如下:

/images/image-20210627204657585.png

解决方案

关于margin塌陷及margin合并的解决方案大概可以分为两个方向:

  1. 避免竖直方向的的margin直接接触。简单来说就是用border、padding或者content将两个直接接触的margin隔开。
  2. 让其脱离标准文档流,而脱离文档流的方法就是触发BFC。

具体解决方案在附录。

BFC

BFC全称为Block Formatting Context(块级格式化上下文)。简单来说就是,提供了一个环境,这个环境中的元素不会影响到外面的布局。

触发BFC的方法

  1. float属性不为none
  2. position属性为absolute或fixed
  3. display为inline-block、table-cell、table-cation、flex、inline-flex
  4. overflow不为visible

附录

Margin塌陷解决方案

避免竖直方向的margin直接接触

  1. 用border隔开

    <body style="background: grey;">
      <div style="height: 500px;background: blue;border: 1px solid red;">
        <div style="height: 200px;background: green;margin-top: 50px;"></div>
      </div>
    </body>
    
  2. 用padding隔开

    <body style="background: grey;">
      <div style="height: 500px;background: blue;padding-top: 1px;">
        <div style="height: 200px;background: green;margin-top: 50px;"></div>
      </div>
    </body>
    
  3. 用content隔开

    <body style="background: grey;">
      <div style="height: 500px;background: blue;">
        content
        <div style="height: 200px;background: green;margin-top: 50px;"></div>
      </div>
    </body>
    

触发BFC

<body style="background: grey;">
  <div style="height: 500px;background: blue;overflow: hidden;">
    <div style="height: 200px;background: green;margin-top: 50px;"></div>
  </div>
</body>

margin合并解决方案

避免竖直方向的margin直接接触

  1. 用border隔开

    <body style="background: grey;">
      <div style="height: 500px;background: blue;">
        <div style="height: 200px;background: green;margin-bottom: 10px;"></div>
        <div style="border: 1px solid red;">
          <div style="height: 200px;background: green;margin-top:50px;"></div>
        </div>
      </div>
    </body>
    
  2. 用padding隔开

    <body style="background: grey;">
      <div style="height: 500px;background: blue;">
        <div style="height: 200px;background: green;margin-bottom: 10px;"></div>
        <div style="padding-top: 1px;">
          <div style="height: 200px;background: green;margin-top:50px;"></div>
        </div>
      </div>
    </body>
    
  3. 用content隔开

    <body style="background: grey;">
      <div style="height: 500px;background: blue;">
        <div style="height: 200px;background: green;margin-bottom: 10px;"></div>
        <div>
          content
          <div style="height: 200px;background: green;margin-top:50px;"></div>
        </div>
      </div>
    </body>
    

触发BFC

<body style="background: grey;">
  <div style="height: 500px;background: blue;">
    <div style="height: 200px;background: green;margin-bottom: 10px;"></div>
    <div style="overflow: hidden;">
      <div style="height: 200px;background: green;margin-top: 50px;"></div>
    </div>
  </div>
</body>