BFC(Block Formatting Context):块级格式化上下文

预备知识

在了解 BFC 之前,我们先来了解 Box 和 Fomatting Context

Box 盒子模型

  • 块级元素(block-level box):块盒 + 行块盒
    • display: block / list-item / inline-block / table的元素是块级元素,并且参与 BFC
  • 行内元素(inline-level box):行盒

    • display: inline / inline-table的元素是行内元素,并且参与 IFC

      Fomatting Context 格式化上下文

      格式化上下文(FC)是 W3C 规范中的一个概念。它是页面中的一块渲染区域,并且有一套渲染规则,它决定了其子元素将如何定位,以及和其他元素的关系、相互作用。
  • W3C CSS2.1 规范中的 FC

    • BFC
    • IFC
  • W3C CSS3 规范中新增的 FC
    • GFC — grid
    • FFC — flex

BFC

1. BFC 的定义

W3C 官方解释为:BFC 它决定了元素如何对其内容进行定位,以及与其它元素的关系和相互作用,当涉及到可视化布局时,Block Formatting Context 提供了一个环境,HTML 在这个环境中按照一定的规则进行布局。

简单来说就是,BFC 是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。

2. BFC 的触发

body 元素就是 BFC

举例会触发 BFC 的 css 属性

  • overflow: 不为 visible
  • float: 不为 none
  • position: absolute / fixed
  • display: inline-block / table / table-caption

display:table 也认为可以生成 BFC,其实这里的主要原因在于 Table 会默认生成一个匿名的 table-cell,正是这个匿名的 table-cell 生成了 BFC

3. BFC 的约束规则

  • BFC 就是一个块级元素,块级元素会在垂直方向一个接一个的排列
  • BFC 就是页面中的一个隔离的独立容器,容器里的标签不会影响到外部标签
  • 垂直方向的距离由 margin 决定, 属于同一个 BFC 的两个相邻的标签外边距会发生重叠
  • 计算 BFC 的高度时,浮动元素也参与计算
  • BFC 的区域不会与 float 的元素区域重叠

常规流布局的约束规则

  • Block 元素会扩展到与父元素同宽,所以block元素会垂直排列
  • 垂直方向上的两个相邻 DIV 的 margin 会重叠,而水平方向不会(此规则并不完全正确)
  • 浮动元素会尽量接近往左上方(或右上方)
  • 为父元素设置overflow:hidden或浮动父元素,则会包含浮动元素

4. BFC 的应用

4.1 防止 margin 重叠(坍塌)

嵌套元素 margin 重叠

image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <style>
  5. body {
  6. margin: 0
  7. }
  8. .box {
  9. margin-top: 20px;
  10. }
  11. .a,.b {
  12. display: inline-block; /* 触发 BFC */
  13. width: 100px;
  14. }
  15. .a {
  16. background-color: red;
  17. height: 50px;
  18. }
  19. .b {
  20. background-color: aqua;
  21. height: 20px;
  22. margin-top: 5px;
  23. }
  24. </style>
  25. </head>
  26. <body>
  27. <div class="box">
  28. <div id="a" class="a">
  29. <div id="b" class="b"></div>
  30. </div>
  31. </div>
  32. </body>
  33. </html>

相邻元素垂直方向 margin 重叠

image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <style>
  5. body {
  6. margin: 0;
  7. }
  8. .background {
  9. background-color: aqua;
  10. }
  11. p {
  12. color: #f55;
  13. background: #fcc;
  14. width: 100px;
  15. text-align: center;
  16. margin: 20px;
  17. }
  18. .bfc {
  19. display: inline-block; /* 触发 BFC */
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="background bfc">
  25. <p class="bfc">Haha</p>
  26. <p>Hehe</p>
  27. </div>
  28. </body>
  29. </html>

4.2 清除内部浮动

image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <style>
  5. body {
  6. margin: 0;
  7. }
  8. .par {
  9. border: 5px solid #fcc;
  10. width: 200px;
  11. }
  12. .child {
  13. border: 5px solid #f66;
  14. width: 50px;
  15. height: 50px;
  16. float: left;
  17. }
  18. .bfc {
  19. /*overflow: hidden;*/ /* 触发 bfc */
  20. }
  21. </style>
  22. </head>
  23. <body>
  24. <div class="par bfc">
  25. <div class="child"></div>
  26. <div class="child"></div>
  27. </div>
  28. </body>
  29. </html>

4.3 自适应多栏布局

image.png

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. <style>
  9. body {
  10. height: 100%;
  11. width: 100%;
  12. margin: 0;
  13. padding: 0;
  14. }
  15. div {
  16. height: 100px;
  17. }
  18. .left {
  19. background: pink;
  20. float: left;
  21. width: 180px;
  22. }
  23. .center {
  24. background: lightyellow;
  25. overflow: hidden; /* 触发 bfc */
  26. }
  27. .right {
  28. background: lightblue;
  29. width: 180px;
  30. float: right;
  31. }
  32. </style>
  33. </head>
  34. <body>
  35. <div class="container">
  36. <div class="left"></div>
  37. <div class="right"></div>
  38. <div class="center"></div>
  39. </div>
  40. </body>
  41. </html>

参考资料

史上最全面、最透彻的BFC原理剖析
面试官:请说说什么是BFC?大白话讲清楚