【面试题解】什么是外边距重叠?如何解决?什么是BFC?

3,003 阅读4分钟

本系列面试题旨在学会相关知识点,从而轻松应对面试题的各种形式,本文讲解了 BFC 以及 利用 BFC 解决外边距重叠问题。

块级格式化上下文(BFC)

BFCBlock Formatting Context

什么是 BFC

BFC 是一个独立的区域,它内部的元素都依照它的规则渲染,并且不会与 BFC 外部打交道。

BFC 的布局规则

  • 内部的盒子会在垂直方向,一个个地放置;
  • 盒子垂直方向的距离由 margin 决定,属于同一个 BFC 的两个相邻盒子的上下 margin 会发生重叠;
  • 每一个元素的左边,与包含块的左边相接触(对于从右往左的布局,则相反),即使存在浮动也是如此;
  • BFC 的区域不会与 float 重叠;
  • BFC 就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此;
  • 计算 BFC 的高度时,浮动元素也參与计算。
  • 当一个元素设置了新的 BFC 后,就和这个元素外部的 BFC 没有关系了,这个元素只会去约束自己内部的子元素。

以下方式会创建 BFC

  • overflow:不为 visible
  • float: 不为 none
  • display: 为 inline-blocktabletable-celltable-captionflexinline-flexgridinline-gridflow-root
  • position: 为 absolute 或者 fixed

可以简单的理解成 OFDP ,当面试官问到你的时候,你回答个 OFDP,面试官大概率就知道你理解这个知识点了。

父子元素边距重叠

场景一:先来看这段代码,预计实现的结果应该是父容器距离页面顶部 100px,子容器距离父容器 100px

 <style>
  body {
    background: gray;
    margin: 0;
    padding: 0;
  }
  .container {
    width: 600px;
    height: 600px;
    background: yellow;
    margin-top: 100px;
  }
  .content {
    width: 200px;
    height: 200px;
    background: green;
    margin-top: 100px;
  }
</style>
<body>
    <div class="container">
      <div class="content"></div>
    </div>
</body>

但是我们却得到了这样的结果,父容器距离页面上方 100px ,但是子容器和父容器之间却没有距离。

image.png

场景二:再来看这段代码,预计实现的结果应该是父容器紧贴页面顶部,子容器距离父容器 100px

 <style>
  body {
    background: gray;
    margin: 0;
    padding: 0;
  }
  .container {
    width: 600px;
    height: 600px;
    background: yellow;
  }
  .content {
    width: 200px;
    height: 200px;
    background: green;
    margin-top: 100px;
  }
</style>
<body>
    <div class="container">
      <div class="content"></div>
    </div>
</body>

结果还是一样的,子容器和父容器之间没有距离,父容器却和页面顶部产生了距离,这是怎么回事呢?

image.png

现象: 发生了边距重叠,一个盒子和其子孙的边距重叠。

规则:正正取最大,负负取最负,正负就相加。

原因:根据规范,一个盒子如果没有添加 BFC,那么它的上边距应该和其文档流中的第一个子元素的上边距重叠。

解决: 通过给父容器添加 overflow: hidden 属性,使之成为 BFC

 .container {
     overflow: hidden;
  }

这回就是我们想要的结果了。

image.png

原理BFC 在页面上是一个独立的容器,父子/外部/内部互不影响。

兄弟元素边距合并

场景三:再来看这段代码,两个兄弟元素,一个下边距是 100px ,另一个上边距 100px ,预计的结果是两个兄弟元素之间的距离是 200px

<style>
  body {
    background: gray;
    margin: 0;
    padding: 0;
  }
  .container {
    width: 600px;
    height: 600px;
    background: yellow;
  }
  .box1 {
    width: 200px;
    height: 200px;
    background: green;
    margin-bottom: 100px;
  }
  .box2 {
    width: 200px;
    height: 200px;
    background: blue;
    margin-top: 100px;
  }
</style>
<body>
    <div class="container">
        <div class="box1"></div>
        <div class="box2"></div>
    </div>
</body>

但是两个兄弟元素之间的距离只有 100px

image.png

现象:发生了边距重叠,两个兄弟元素的上边距和下边距发生了重叠。

规则:正正取最大,负负取最负,正负就相加。

原因:块级元素的上外边距或下外边距有时(直接接触/相邻时)会合并为一个外边距。

解决:通过给其中一个兄弟元素添加父容器并添加 overflow: hidden 属性,使之成为 BFC

<style>
  body {
    background: gray;
    margin: 0;
    padding: 0;
  }
  .container {
    width: 600px;
    height: 600px;
    background: yellow;
  }
  .father {
    overflow: hidden;
  }
  .box1 {
    width: 200px;
    height: 200px;
    background: green;
    margin-bottom: 100px;
  }
  .box2 {
    width: 200px;
    height: 200px;
    background: blue;
    margin-top: 100px;
  }
</style>
<body>
    <div class="container">
      <div class="father">
        <div class="box1"></div>
      </div>
      <div class="box2"></div>
    </div>
</body>

这回就是我们想要的结果了。

image.png

原理:属于不同 BFC 的元素垂直方向边距不会发生重叠。

空元素边距合并

场景四:两个兄弟元素之间有四个空元素,每个空元素有 25pxmargin-top,预计的结果是两个兄弟元素之间的距离是 100px

<style>
  body {
    background: gray;
    margin: 0;
    padding: 0;
  }
  .container {
    width: 600px;
    height: 600px;
    background: yellow;
  }
  .box1 {
    width: 200px;
    height: 200px;
    background: green;
  }
  .box2 {
    width: 200px;
    height: 200px;
    background: blue;
  }
  .null {
    margin-top: 25px;
  }
</style>
<body>
    <div class="container">
      <div class="box1"></div>
      <p class="null"></p>
      <p class="null"></p>
      <p class="null"></p>
      <p class="null"></p>
      <div class="box2"></div>
    </div>
</body>

但是结果却是只有一个空元素的距离,也就是 25px

image.png

现象:发生了边距重叠,所有的空元素的边距重叠成一个空元素的边距。

原因:如果一个块级元素没有任何内容并且设置了 margin-topmargin-bottom 时会发生 margin 合并。

解决:给每一个添加父容器并添加 overflow: hidden 属性,使之成为 BFC

<style>
  body {
    background: gray;
    margin: 0;
    padding: 0;
  }
  .container {
    width: 600px;
    height: 600px;
    background: yellow;
  }
  .box1 {
    width: 200px;
    height: 200px;
    background: green;
  }
  .box2 {
    width: 200px;
    height: 200px;
    background: blue;
  }
  .null {
    margin-top: 25px;
  }
  .father {
    overflow: hidden;
  }
</style>
<body>
    <div class="container">
      <div class="box1"></div>
      <div class="father">
        <p class="null"></p>
      </div>
      <div class="father">
        <p class="null"></p>
      </div>
      <div class="father">
        <p class="null"></p>
      </div>
      <div class="father">
        <p class="null"></p>
      </div>
      <div class="box2"></div>
    </div>
</body>

这样就达到了我们的目的。但是这种情况实际应用场景几乎没有,了解一下就行。

image.png

原理:属于不同 BFC 的元素垂直方向边距不会发生重叠。

感觉有帮助的小伙伴请点赞👍支持一下,谢谢~