原稿:语雀 · 外边距叠加 · 原目录:CSS › CSS 知识点 › 外边距叠加

先上结论,外边距叠加的解决方法

  • 兄弟叠加:给每个元素设置外部 BFC 容器
  • 父子叠加:父元素创建 BFC、父元素使用 padding-top/bottom 或 border-top/bottom、父元素
  • 不常用方法(可能影响布局):修改元素为绝对布局、浮动或非块级元素

参考链接:

什么是外边距叠加

在CSS中,两个或多个毗邻的普通流中的块级盒子(可能是父子元素,也可能是兄弟元素)在垂直方向上的外边距会发生叠加,这种形成的外边距称之为外边距叠加。(见w3文档

  1. 同一个 BFC 内的块级盒子
  2. 两个或多个:数量必须是大于一个,又说明,折叠是元素与元素间相互的行为,不存在 A 和 B 折叠,B 没有和 A 折叠的现象
  3. 毗邻:指元素间没有被非空内容、padding、border 分隔开
  4. 垂直方向:指具体的方位,只有垂直方向的 margin 才会折叠,水平方向的 margin 不会发生折叠的现象

外边距叠加存在两种情况:一是父子外边距叠加;二是兄弟外边距叠加


兄弟叠加

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>double-col</title>
    <style>
      .container {
        width: 400px;
        height: 400px;
        padding-top: 40px;
        margin: 0 auto;
        background-color: hotpink;
      }
      .child1 {
        margin: 50px 0;
        width: 100px;
        height: 100px;
        background-color: rgb(21, 121, 253);
      }
      .child2 {
        margin: 30px 0;
        width: 100px;
        height: 100px;
        background-color: rgb(240, 23, 23);
      }
    </style>
  </head>
  <body>
    <div class="container">


    </div>
  </body>
</html>

查看结果,可以看到因为 child1 的 margin-bottom 与 child2 的 margin-top 毗邻,满足外边距叠加的三个条件,则叠加并保留为二者中较大的 50px

.child2

.child1

image.png
image.png

父子叠加

父子叠加发生于

  • 父元素和第一个块级子元素的 margin-top
  • 父元素和最后一个块级子元素的 margin-bottom
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <title>double-col</title>
    <style>
      .container {
        width: 400px;
        height: 400px;
        margin: 0 auto;
        background-color: hotpink;
      }
      .child {
        margin: 50px 0;
        width: 100px;
        height: 100px;
        background-color: rgb(21, 121, 253);
      }
    </style>
  </head>
  <body>
    <div class="container">

    </div>
  </body>
</html>

首先是上面的代码,父元素竖直 margin 为 0,子元素竖直 margin 为 50px,效果如图,可以看到父子元素的 border box 边缘重合,边距叠加后统一为 50px

image.png

修改代码,为父元素添加 padding-top 或者 border-top(border 必须显式设置样式,因为默认为 none)。这是执行的结果立刻不同,可以看到父元素不再有 margin-top,而子元素的边距 margin-top 重写回到了正确的位置——padding-top 或 border-top 破坏了父子元素 margin-top 的毗邻关系,因此边距叠加失效

/* border-top: solid 1px; */
padding-top: 1px;
image.png

修正边距叠加

主要基于以下三点:

  • 同一个 BFC 内正常流的块级元素才会可能边距叠加,则可以
  • 脱离正常流=》设置元素本身浮动
  • 脱离正常流=》设置元素为绝对定位
  • 非块级元素=》设置元素为 inline-block
  • 创建了 BFC 的元素不会和它的子元素发生外边距叠加,则可以通过这四种方式创建 BFC
  • float(除了none)
  • overflow(除了visible)
  • display(table-cell/table-caption/inline-block)
  • position(除了static/relative)
  • 避免毗邻,创造间隙

综上,可获得如下解决方案:其中令元素脱离正常流或者变成非块级元素的方法恰好是创建 BFC 方法的子集

兄弟

  • 令元素本身为 display:inline-block、position:absolute、float
  • 这种方案对元素本身布局影响较大,因此更常见的方法是为元素设置外部 BFC 容器
  • 给每个元素设置外部 BFC 容器:对每个元素设置外部容器,容器上使用 display:inline-block、position:absolute、float 、overflow 之一

父子

  • 令子元素本身为 display:inline-block、position:absolute、float
  • 实际少用,理由同上
  • 让父元素创建 BFC
  • 设置父元素的 padding-top、border-top,避免毗邻状态