关于块格式化上下文(BFC)

304 阅读4分钟

每次谈到块格式化上下文(简称 BFC),脑袋里总是感觉懵懵的,今天写一篇博客,梳理一下知识点。

块格式化上下文,说复杂也复杂,总给人一种神妙的感觉,但是就在应用的层面上来说,牢牢记住几个关键点,清楚 BFC 大概是什么、怎么创建一个 BFC、BFC 有什么特点、BFC 有什么作用,其实也就没什么复杂的了。

BFC 是啥

先看一下官方的文档解释:

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

每句话都通俗地理解一下,在 web 页面中,BFC 就是渲染可以看见的 css 内容的一部分,是一个能够让块盒子布局的区域,在该区域中也能让浮动元素与其他元素进行交互。其实在我们不知道 BFC 的时候,我们难道不就是在渲染 css、做块盒子布局、必要的时候让元素浮动吗?是的,那是因为我们本来就在一个 BFC 中进行布局,在下文的 BFC 创建条件中,就可以看到根元素就会创建一个 BFC 。

BFC 创建条件

以下是 BFC 的创建条件:

  • 根元素(也就是 <html> 标签)
  • overflow 不为 visible 的元素
  • positon 为 absolute 或 fixed 的元素
  • float 不为 none 的元素(浮动元素)
  • display 为以下值的元素:① flow-root。 ② inline-block(行内块元素)。 ③ flex 或 inline-flex 元素的直接子元素。 ④ grid 或 inline-grid 元素的直接子元素。 ⑤ table-cell(表格单元格) ⑥ table-caption(表格标题) ⑦ table、table-row、table-row-group、table-header-group、table-footer-group、inline-table。
  • contain 值为 content、layout、paint(contain 值不为none、strict、size、style)
  • column-span 值为 all 的元素,即使该元素没有包裹在一个多列容器中。
  • 多列容器,column-count 或 column-width 不为 auto 的元素。

BFC 中的元素有哪些特点

第一个特点是 BFC 元素特性的表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素。

第二个特点是 BFC 中的盒子对齐:在 BFC 中,每个盒子的左外边框紧挨着包含块的左边框(从右到左的格式,则为紧挨右边框)。即使存在浮动也是这样的(尽管一个盒子的边框会由于浮动而收缩),除非这个盒子的内部创建了一个新的BFC浮动,盒子本身将会变得更窄。

可以用 BFC 做什么

1.防止因浮动导致高度塌陷

高度塌陷是指当为一个元素设置为浮动后,那么该元素就会脱离常规流,对于其他处于常规流的元素来说就好像该浮动的元素不存在一样,所以该浮动元素的父元素的高度就不会包含该浮动元素,若父元素中除了此浮动元素外没有其他内容,那么这个父元素的高度就会显示为0,这就是高度塌陷问题。

//html:
  <div class="outer">
    <div class="inner"></div>
  </div>
//css:
.outer{
  border:1px solid red;
}
.inner{
  width:100px;
  height:100px;
  background:green;
  float:left;
}

结果:

怎么解决高度塌陷问题呢?也就是怎么让浮动元素的父元素的高度能够包含浮动元素,可以用清除浮动的那些办法,在这里我们利用 BFC 来解决,那就是让这个父元素创建一个 BFC ,可以给这个父元素设置上述 BFC 的创建条件中的任何一个属性,当父元素创建了一个 BFC 之后,其高度就能够包含浮动元素了。

2.防止外边距折叠

在常规文档流中,盒子都是从包含块的顶部开始一个接着一个垂直堆放,如果两个兄弟盒子在同一个 BFC 中,那么他们之间的垂直距离则是由他们单个个体的外边距所决定的,而不是他们的两个外边距之和,若外边距的值不相同,则按照值大的为准。若要防止外边距折叠,则需要将其中的一个兄弟元素包含在一个新的 BFC 里面,这样他们就属于不同的 BFC 中了,该元素也就不会和其兄弟元素之间存在外边距折叠问题了。见代码:

//html:
  <div class="outer">
    <div class="div1"></div>
    <div class="div2"></div>
    <div class="newBfc">
      <div class="div3"></div>
    </div>
  </div>
//css:
.outer{
  border:1px solid red;
  overflow:hidden;
}
.div1 {
  width: 30px;
  height: 30px;
  background: red;
  margin: 10px 0;
}
.div2 {
  width: 30px;
  height: 30px;
  background: green;
  margin: 10px 0;
}
.div3 {
  width: 30px;
  height: 30px;
  background: black;
  margin: 10px 0;
}
.newBfc{
  display:flow-root;  //创建一个 BFC
}

结果:

3.解决文字环绕问题

参考文章:理解CSS中BFC

4.多列布局最后一个元素溢出问题

参考文章:理解CSS中BFC

本文参考:

理解CSS中BFC

CSS深入理解流体特性和BFC特性下多栏自适应布局--张鑫旭

本文只是简要介绍了一下 BFC,更多内容欢迎留言讨论。