css中的BFC

81 阅读4分钟

BFC

BFC是 块级格式化上下文。

二、如何创建(开启)BFC?

创建 BFC 并不是通过一个特定的 CSS 属性 bfc: true 来实现的,而是通过应用某些特定的 CSS 属性来“触发”或“开启”一个元素的 BFC 特性。以下是常见的触发方式:

  1. 根元素 <html>

    • 页面最大的 BFC 就是 <html> 元素。
  2. 浮动元素

    • float 的值不为 none(即 left 或 right)。
  3. 绝对定位元素

    • position 的值为 absolute 或 fixed
  4. 行内块元素

    • display 的值为 inline-block
  5. 表格单元格

    • display 的值为 table-cell 或 table-caption。
  6. 弹性盒子(Flexbox)的子项

    • display 的值为 flex 或 inline-flex 的直接子元素。
  7. 网格布局(Grid)的子项

    • display 的值为 grid 或 inline-grid 的直接子元素。
  8. overflow 属性

    • overflow 的值不为 visible(即 hiddenautoscroll)。这是最常用、副作用最小的创建 BFC 的方法。
  9. display: flow-root;

    • 这是一个专门为了创建 BFC 而生的新属性。它的唯一作用就是创建一个无副作用的 BFC,是目前最推荐的现代方法。

小结:在日常开发中,最常用且最推荐的创建 BFC 的方法是 overflow: hidden; 和 display: flow-root;。

三、BFC 解决了什么问题?(BFC 的应用)

BFC 的核心价值在于它的“隔离”和“内部特殊布局规则”。正是这些特性,让它能巧妙地解决以下几个经典的 CSS 布局难题。

1. 解决问题一:清除内部浮动防止父元素高度塌陷

这是 BFC 最最最经典的应用场景。

  • 问题描述:当一个父元素内部只包含浮动元素时,由于浮动元素脱离了正常的文档流,父元素会无法感知其高度,导致父元素的高度“塌陷”为 0。这会影响后续元素的布局。

  • 示例

    codeHtml

    <div class="parent">
      <div class="child"></div>
    </div>
    <div class="footer">Footer</div>
    

    codeCSS

    .parent {
      border: 2px solid red;
    }
    .child {
      float: left;
      width: 100px;
      height: 100px;
      background: lightblue;
    }
    

    在这个例子中,红色的边框会“塌陷”成一条线,因为 .parent 的高度为 0。

  • BFC 解决方案:给父元素 .parent 触发 BFC。

    codeCSS

    .parent {
      border: 2px solid red;
      overflow: hidden; /* 触发 BFC */
      /* 或者 display: flow-root; */
    }
    
  • 原理解释:BFC 的一个重要规则是:在计算 BFC 的高度时,其内部的浮动元素也参与计算。  当 .parent 成为一个 BFC 后,它就像一个负责任的家长,会去“关照”它内部所有调皮的浮动孩子,把它们的高度也算作自己的高度。这样,父元素的高度就被正确地撑开了。

2. 解决问题二:防止外边距折叠(Margin Collapse)

  • 问题描述:在正常的文档流中,相邻的两个块级元素的**垂直外边距**会发生“折叠”,即取两者中较大的那个值作为它们之间的间距,而不是简单相加。这在兄弟元素之间和父子元素之间都可能发生。

  • 示例(兄弟元素)

    codeHtml

    <div style="margin-bottom: 20px; background: lightcoral;">Box 1</div>
    <div style="margin-top: 30px; background: lightskyblue;">Box 2</div>
    

    Box 1 和 Box 2 之间的实际间距是 30px,而不是 20px + 30px = 50px。

  • BFC 解决方案:将其中一个元素用一个 BFC 容器包裹起来。

    codeHtml

    <div style="margin-bottom: 20px; background: lightcoral;">Box 1</div>
    <div style="overflow: hidden;"> <!-- 创建一个 BFC 容器 -->
      <div style="margin-top: 30px; background: lightskyblue;">Box 2</div>
    </div>
    
  • 原理解释:BFC 的另一个重要规则是:BFC 是一个独立的容器,它内部的元素外边距不会与外部的元素发生折叠。  当我们用一个 BFC 包裹住 Box 2 后,Box 2 的 margin-top 就被“关”在了这个 BFC 内部,它只能和 BFC 容器的边框发生关系,而无法“穿透” BFC 去和外面的 Box 1 发生折叠。

3. 解决问题三:自适应两栏(或三栏)布局

  • 问题描述:我们想实现一个经典的布局:左边栏固定宽度,右边栏自适应剩余宽度。如果简单地让左边栏 float: left,右边栏不设置浮动,右边栏的文字会环绕在左边栏周围,其背景和边框会延伸到左边栏的下方。

  • 示例

    codeHtml

    <div class="left">Left</div>
    <div class="right">Right content will wrap around the left floated element...</div>
    

    codeCSS

    .left {
      float: left;
      width: 200px;
      height: 150px;
      background: lightcoral;
    }
    .right {
      height: 200px;
      background: lightskyblue;
    }
    

    你会看到,蓝色的背景铺满了整个宽度,覆盖了左边栏的下方。

  • BFC 解决方案:给右边栏 .right 触发 BFC。

    codeCSS

    .right {
      height: 200px;
      background: lightskyblue;
      overflow: hidden; /* 触发 BFC */
    }
    
  • 原理解释:BFC 的第三个重要规则是:BFC 的区域不会与浮动元素的区域发生重叠  当 .right 成为一个 BFC 后,它会感知到旁边有一个浮动元素 .left 占了空间。为了不与它重叠,BFC 会自动计算自己可用的剩余宽度,并收缩自己的布局范围,从而完美地实现了自适应布局。