CSS BFC
在进行html布局及css编写的时候,是否遇到过这样的问题:

  • 子元素设置浮动脱离文档流后,父元素无法将其完全包裹
  • 子元素浮动实现两栏布局时,另一个子元素与浮动子元素重叠
  • 垂直方向的外边距margin重叠

通常使用块级格式化上下文(BFC)就能解决以上问题。

什么是BFC

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
FC(formatting context)直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。
BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素,并且容器元素不会影响兄弟元素的布局。

什么情况下会创建BFC

  • 根元素或包含根元素的元素
  • 浮动元素(元素的 float 不是 none)
  • 绝对定位元素(元素的 position 为 absolute 或 fixed)
  • 行内块元素(元素的 display 为 inline-block)
  • 表格单元格(元素的 display为 table-cell,HTML表格单元格默认为该值)
  • 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  • 匿名表格单元格元素(元素的 display为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot的默认属性)或 inline-table)
  • overflow 值不为 visible 的块元素
  • display 值为 flow-root 的元素(新方式,文末会提及)
  • contain 值为 layout、content或 strict 的元素
  • 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
    column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中。

    常见应用场景

    使父元素包含浮动元素

    下面例子解释如何让浮动内容和父元素等高,清楚浮动负面影响
    html
    1. <div class="outer">
    2. <div class="float">I am a floated element.</div>
    3. I am text inside the outer box.
    4. </div>
    css ```css .outer { border: 5px dotted rgb(214,129,137); border-radius: 5px; width: 450px; padding: 10px; margin-bottom: 40px; }

.float { padding: 10px; border: 5px solid rgba(214,129,137,.4); border-radius: 5px; background-color: rgba(233,78,119,.4); color: #fff; float: left;
width: 200px; margin: 0 20px 0 0; }

  1. 通过给左侧文字设置向左浮动实现文字环绕效果是很常见的做法,当文本足够长时,会看到如下效果,父元素可以完全包裹子元素。<br />![](https://cdn.nlark.com/yuque/0/2021/jpeg/396745/1613799505766-a344ff3c-babf-4bf7-95d1-f555f64c2cfb.jpeg#align=left&display=inline&height=351&originHeight=351&originWidth=800&size=0&status=done&style=shadow&width=800)<br />但事实上,float中的文字已经脱离文档,如果文档流文字过少,浮动元素就会溢出父元素边缘。<br />![](https://cdn.nlark.com/yuque/0/2021/jpeg/396745/1613799505762-c3e78f8a-b9b7-4388-9e12-0e822b87c1a4.jpeg#align=left&display=inline&height=199&originHeight=199&originWidth=800&size=0&status=done&style=shadow&width=800)<br />这时候为父元素设置`overflow: auto`或者除`invisible`默认值之外的任何有效值都能创建BFC解决这个问题,使父元素包含浮动元素
  2. ```css
  3. .outer {
  4. overflow: auto;
  5. }

CSS布局和块格式化上下文 - 图1

BFC防止垂直外边距重叠

外边距折叠的规则是:当两个块级元素相邻并且在同一个块级格式化上下文时,它们垂直方向上的外边距会产生重叠
html

  1. <div class="outer">
  2. <p>I am paragraph one and I have a margin top and bottom of 20px</p>
  3. <p>I am paragraph two and I have a margin top and bottom of 20px</p>
  4. </div>

css

  1. .outer {
  2. background-color: #ccc;
  3. margin: 0 0 40px 0;
  4. }
  5. p {
  6. padding: 0;
  7. margin: 20px 0 20px 0;
  8. background-color: rgb(233,78,119);
  9. color: #fff;
  10. }

由于p元素的边缘和外部div上的边距之间没有内容,因此两者将会合并,因此段落最终与框的顶部和底部齐平。在段落的上方和下方看不到任何灰色。如下图:
CSS布局和块格式化上下文 - 图2
当父元素设置了BFC之后,父元素与子元素p重叠区域将不再合并

  1. .outer {
  2. background-color: #ccc;
  3. margin: 0 0 40px 0;
  4. overflow: auto;
  5. }

CSS布局和块格式化上下文 - 图3

BFC防止文本环绕

依然像上面例子文字环绕效果的布局和样式
html

  1. <div class="outer">
  2. <div class="float">I am a floated element.</div>
  3. <div class="text">I am text...</div>
  4. </div>

css

  1. .float{
  2. float: left;
  3. }

CSS布局和块格式化上下文 - 图4
这时候如果不想要右侧文字环绕浮动文字盒子,在左侧div设置浮动的情况下,可以通过使右边div成为BFC,使两个兄弟div互相隔离、互不影响,从而达到去除文字环绕的效果。

  1. .text {
  2. overflow: auto;
  3. }

CSS布局和块格式化上下文 - 图5

创建BFC的新方式

创建BFC的许多方法通常会带来一些副作用,目前为止似乎最安全的就是overflow属性,但某些情况下不需要滚动条,此时滚动条就变成了这种方式的副作用,因此display有个新的属性flow-root可以在任何需要创建BFC场景下使用,它并且不会带来任何副作用。
flow-root浏览器兼容情况:
image.png
浏览器对此值的支持是有限的,如果要在不支持flex或网格布局浏览器创建回退,了解BFC阻止浮动元素的负面影响十分必要。