BFC(边距重叠解决方案)

1,971 阅读4分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

BFC(块级格式化上下文)

  • 块格式化上下文是页面上的一个独立的渲染区域,容器里面的子元素不会在布局上影响外面的元素。
  • 它是决定块盒子的布局及浮动元素相互影响的一个因素。

css在什么情况会创建一个块格式化上下文

  1. 根元素,即HTML元素(最大的一个BFC)
  2. 浮动(float的值不为none)
  3. 绝对定位元素(position的值为absolute或fixed)
  4. 行内块(display为inline-block)
  5. 表格单元(display为table、table-cell等HTML表格相关属性)
  6. 弹性盒(display为flex或inline-flex)
  7. 默认值。内容不会被修剪,会呈现在元素框之外(overflow不为visible)

BFC的作用

📌1. 让父元素包含子浮动元素,清除内部浮动。(对子元素设置浮动后,父元素会发生高度塌陷,也就是父元素的高度变为0。)

.father {
  /* 父级没有设置高度,子元素浮动,产生父元素高度塌陷 */
  width: 100px;
  background-color: burlywood;
}
.children {
  float: left;
  width: 50px;
  height: 50px;
  background-color: coral;
}
<!-- 1. 清除内部浮动 -->
<div class="father">
  <div class="children"></div>
</div>
  • 父级没有设置高度,子元素浮动,产生父元素高度塌陷

    BFC作用之清除内部浮动.png

  • 解决方法:只需要把父元素变成一个BFC即可,常用的方法是给父元素设置overflow:hidden

    .father {
      /* 父级没有设置高度,子元素浮动,产生父元素高度塌陷 */
      width: 100px;
      /* 解决高度塌陷,把父元素变成BFC */
      overflow: hidden;
      border: 3px solid burlywood;
    }
    
  • 设置父元素变成BFC后,遵循BFC布局规则第6条: 计算BFC的高度时,浮动元素也参与计算

    BFC作用之清楚内部浮动解决后.png

📌2. 上下margin重合问题。(分属于不同的BFC时,可以阻止margin重叠)

.father {
  width: 100px;
  border: 3px solid rgb(83, 141, 230);
}
.children1 {
  width: 50px;
  height: 50px;
  margin-bottom: 10px;
  background-color: coral;
}
.children2 {
  width: 50px;
  height: 50px;
  margin-top: 10px;
  background-color: coral;
}
<div class="father">
  <div class="children1"></div>
  <div class="children2"></div>
</div>
  • 如图所示:虽然两个子元素都设置了外部的margin,但是只有两元素之间只有10px,并非20px

    BFC作用之上下margin重合问题.png

  • 解决方法:给任意一个子元素的外侧包裹一个块级元素,并为这个块级元素设置overflow:hidden

.box {
  overflow: hidden;
}
<div class="father">
  <div class="children1"></div>
  <div class="box">
    <div class="children2"></div>
  </div>
</div>
  • 遵循BFC布局规则第2条:Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Boxmargin会发生重叠

    BFC作用之上下margin重合问题解决后.png

  • 注意:应该避免这样添加margin,尽量在同一个方向给元素添加,例如:都添加顶部margin

📌3. 元素被浮动元素覆盖问题

.aside {
  float: left;
  width: 100px;
  height: 150px;
  background-color:coral;
}
.main {
  height: 200px;
  background-color: rgb(238, 190, 150);
}
<div class="aside"></div>
<div class="main"></div>
  • 如图所示:浮动的元素覆盖住了后面的元素

    BFC作用之元素覆盖问题.png

  • 为什么会这样?因为BFC布局规则第3条规定:每个元素的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。因此,虽然存在浮动的元素`aside,但main的左边依然会与包含块的左边相接触。

  • 解决方法遵循BFC布局规则第4条:BFC的区域不会与float box重叠。通过触发main生成BFC,来实现。

.main {
  /* 将其转换为BFC */
  overflow: hidden;
}
  • 适用场景: 自适应两(三)栏布局(避免多列布局由于宽度计算四舍五入而自动换行)

    BFC作用之自适应两栏布局.png

  • 左图右文

    img {
      float: left;
      width: 100px;
      height: 100px;
    }
    .box {
      width: 30px;
      height: 30px;
      background-color: cornflowerblue;
    }
    p {
      overflow: hidden;
      width: 100px;
    }
    
    <img src="./img/sky.webp" alt="天空">
    <div class="box"></div>
    <p>超长的文字</p><p>超长的文字</p>
    <p>超长的文字</p><p>超长的文字</p>
    
  • 如图BFC作用之float文字环绕.png

  • 问题:为什么 div 的左上角被覆盖了,而文本却没有被覆盖?因为div会被float覆盖,而文本却没有被float覆盖,是因为float当初设计的时候就是为了使文本围绕在浮动对象的周围。

总结

  • 其实以上的例子都体现了BFC的第5条布局规则:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。
  • BFC布局规则:
    • 第1条:内部的Box会在垂直方向,一个接一个地放置。
    • 第2条:Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
    • 第3条:每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
    • 第4条:BFC的区域不会与float box重叠。
    • 第5条:BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
    • 第6条:计算BFC的高度时,浮动元素也参与计算