图文讲解CSS之BFC

697 阅读6分钟

前言

它解决了早期Web页面布局中的一系列问题,使得布局更加精确和可控,同时也支持了更复杂和灵活的布局需求:

1)解决浮动问题

在CSS早期,浮动(float)被广泛用于布局,但它带来了一系列问题,如父元素的高度塌陷、元素重叠等。

BFC提供了一种机制,能够隔离浮动元素和它们外部的元素,防止这些问题发生。通过创建新的BFC,可以使得父元素能够包含浮动的子元素,解决高度塌陷的问题。

2)提供更精确的布局控制

BFC规定了内部Box的布局方式,使得开发者可以更精确地控制布局。

在BFC中,盒子会在垂直方向上一个接一个地放置,盒子之间的垂直距离由 margin 决定。

这个特性也为解决外边距折叠(margin collapsing)提供了方法。

3)隔离元素,防止外部样式干扰

BFC可以看作是一个独立的容器,容器内部的布局不会影响到外部环境,同样外部的布局也不会影响到容器内。

这对于组件化开发非常有用,因为它允许开发者将页面分割成多个独立的部分,每部分都有自己的布局规则,互不干扰。

4)支持复杂的布局需求

随着Web应用的发展,页面布局越来越复杂。BFC提供了一种机制,支持如多栏布局等复杂的布局需求。

例如,通过创建BFC,可以防止旁边的元素环绕另一个元素,支持创建并列的布局结构

什么是BFC

区块格式化上下文(Block Formatting Context,BFC)是 Web 页面的可视 CSS 渲染的一部分,是块级盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

BFC有什么作用和特点

它有一套属于自己的渲染规则:

  • 内部的盒子会在垂直方向上一个接一个地放置。
  • 对于同一个BFC内的两个相邻的块级盒子的垂直距离由它们的margin决定。这称为垂直外边距折叠。
  • 每个元素的左外边距与包含块的左边界相接触。即使存在浮动也是如此(这是 BFC 的一个主要特点,可用于清除浮动)。
  • BFC 的区域不会与浮动盒子重叠。
  • 计算 BFC 的高度时,浮动元素也参与计算。
  • BFC 就是页面上的一个隔离的独立渲染区域,独立渲染区域里面的子元素不会影响到外面的元素。反之亦然。

BFC的触发条件

  • 文档的根元素(<html>)。
  • 浮动元素(即 float 值不为 none 的元素)。
  • overflow 值不为 visible 或 clip 的块级元素,为auto、scroll、hidden。
  • 绝对定位元素(position 值为 absolute 或 fixed 的元素)。
  • display值为:flow-root、inline-block、table-cell、table-caption、table、table-row、inline-table、flex、inline-flex、grid、inline-grid
  • 更多

BFC的应用

display: flow-root :一个新的 display 属性的值,它可以创建无副作用的 BFC。

在父级块中使用 display: flow-root 可以创建新的 BFC。

1. 防止外边距折叠(又称外边距溢出)

在一个 BFC 中,块级盒子的垂直外边距会发生折叠。通过创建新的 BFC,可以避免外边距折叠的问题。

1) 相邻兄弟元素的外边距折叠

<section>
  <div class="blue"></div>
  <div class="red"></div>
</section>
.blue,
.red {
  height: 30px;
}

.blue {
  background: blue;
  margin-bottom: 10px;
}

.red {
  background: red;
  margin-top: 20px;
}

image.png

第一个元素的下外边距和第二个元素的上外边距会折叠,它们之间的实际外边距将是两者之间较大的那个外边距值,而不是两者之和。

我们可以通过触发BFC 隔离的独立渲染区域,来避免垂直方向的margin合并。

<section>
  <div class="blue"></div>
  <div style="display: flow-root">
    <div class="red"></div>
  </div>
</section>

image.png

2) 父元素与其第一个或最后一个子元素的外边距折叠

如果父元素不含边框、内边距(padding)以及水平方向的分隔(比如内联元素),且父元素与其第一个或最后一个子元素之间没有创建块级格式化上下文(BFC),那么它们之间的外边距也会发生折叠。

<div class="parent">
  <div class="child">子元素</div>
</div>
.parent {
  border: none;
  padding: 0;
  background-color: red;
}
.child {
  margin-top: 30px;
}

image.png

如上,子元素的上外边距会“溢出”到父元素之外,使得父元素与子元素之间看起来没有外边距, 同样,触发BFC,即可避免外边距折叠(当然,为元素添加内边距padding或边框border也可以阻止外边距折叠)

image.png

3) 空的块级元素的外边距折叠

如果一个块级元素没有内容、边框和内边距,它的上下外边距也会折叠。

<div class="box"></div>
<div class="empty"></div>
<div class="box"></div>
 .empty {
    margin-top: 30px;
    margin-bottom: 30px;
  }
  .box {
    height: 30px;
    background-color: red;
  }

image.png

empty 元素的上下外边距将折叠,实际的外边距是30px,而不是两者之和。同样,我们也可以通过创建块级格式化上下文(BFC)或者为元素添加内边距或边框可以阻止外边距折叠。

2. 清除浮动

由于 BFC 可以包含浮动元素(不被浮动元素覆盖),通过给父元素创建 BFC 可以清除子元素的浮动,避免父元素高度塌陷

<section>
  <div class="box">
    <div class="float">我是浮动的盒子!</div>
  </div>
</section>
<section>
  <div class="box" style="display: flow-root">
    <div class="float">我是浮动的盒子!</div>
  </div>
</section>
section {
  height: 150px;
}
.box {
  background-color: rgb(224, 206, 247);
  border: 5px solid rebeccapurple;
}
.box[style] {
  background-color: aliceblue;
  border: 5px solid steelblue;
}
.float {
  float: left;
  width: 200px;
  height: 100px;
  background-color: rgba(255, 255, 255, 0.5);
  border: 1px solid black;
  padding: 10px;
}

image.png

浮动的元素会脱离普通文档流,容器只剩下2px的边距高度,创建容器的 BFC,容器将会包裹浮动元素。BFC使得浮动内容和周围的内容等高

3. 自适应两栏布局

利用 BFC 的性质,让浮动和非浮动元素自适应并排

 <section>
  <div class="float">我是浮动的盒子</div>
  <div class="box">会显示文字环绕效果会显示文字环绕效果会显示文字环绕效果会显示文字环绕效果会显示文字环绕效果</div>
</section>
<section>
  <div class="float">我是浮动的盒子</div>
  <div class="box" style="display: flow-root">不会显示文字环绕效果不会显示文字环绕效果不会显示文字环绕效果不会显示文字环绕效果</div>
</section>
 section {
   height: 120px;
}
.box {
  background-color: rgb(224, 206, 247);
  border: 5px solid rebeccapurple;
}
.box[style] {
  background-color: aliceblue;
  border: 5px solid steelblue;
}
.float {
  float: left;
  width: 100px;
  height: 40px;
  background-color: rgba(255, 255, 255, 0.5);
  border: 1px solid black;
  padding: 10px;
}

image.png 正常文档流中建立的 BFC 不得与元素本身所在的块格式化上下文中的任何浮动的外边距重叠

小结

BFC的引入是CSS发展过程中的一个重要里程碑。体现了Web标准在不断发展和完善中,对布局模型的优化和提升。

参考

MDN-区块格式化上下文