~/static/img/default-avatar-0.jpeg

yinanchen

前端开发工程师

博客

什么是BFC?

yinanchen 2022-03-13

正常文档流 Normal flow

在普通流中,盒子会依次放置。在块格式化上下文中,盒子在垂直方向依次排列;而在行内格式化上下文中,盒子则水平排列。当CSS的** position 属性为 static relative ,并且 float none **时,其布局方式为普通流。

https://www.w3.org/TR/CSS2/visuren.html#block-formatting

Boxes in the normal flow belong to a formatting context, which may be block or inline, but not both simultaneously. Block-level boxes participate in a block formatting context. Inline-level boxes participate in an inline formatting context.

翻译一下:正常文档流下,盒模型归属到格式化上下文。块级盒子参加块级格式化上下文。内联盒子参加内联格式化上下文。

FC

https://drafts.csswg.org/css-display/#formatting-context

A formatting context is the environment into which a set of related boxes are laid out. Different formatting contexts lay out their boxes according to different rules.

格式化上下文是决定盒子之间如何布局的环境,不同的格式化上下文如何布局盒子由自身的规则来决定。

BFC

https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context

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

https://zhuanlan.zhihu.com/p/25321647

具有 BFC 特性的元素可以看作是隔离了的独立容器,容器里面的元素不会在布局上影响到外面的元素,并且 BFC 具有普通容器所没有的一些特性。

BFC规则

  • 内部盒子会在垂直方向排列
  • 同一个BFC上环境下的元素可能发生margin collapse
  • BFC就是页面上的一个隔离的独立容器,里外互相不受影响
  • 计算BFC的高度时,考虑BFC所包含的所有子元素,连浮动元素也要参与计算。
  • 当元素不是BFC的子元素时,浮动元素高度不参与BFC计算(常见的盒子塌陷问题)
  • 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  • BFC的区域不会与float box重叠。

BFC触发条件

  • 根元素html
  • float元素不为none
  • position为absolute或fixed
  • display为inline-block, table-cell, table-caption, flex, inline-flex
  • overflow不为visible

如何理解BFC的应用

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>

    </style>
  </head>

  <body>

  </body>
</html>
  • 内部盒子会在垂直方向排列
  • 同一个BFC上环境下的元素可能发生margin collapse
  • BFC就是页面上的一个隔离的独立容器,里外互相不受影响

可能我们的页面是很复杂的页面,但是初始我们的页面书写都是基于上面的结构。此时整个文档流只有一个BFC环境,那就是html 。所以内部的元素存在盒子塌陷,浮动等问题,是根据规则来的。所以我们在内部创建了新的BFC根据上面规则第三条。就可以解决相关的问题。

例子1:margin重叠

  • 同一个BFC上环境下的元素可能发生margin collapse
  • BFC就是页面上的一个隔离的独立容器,里外互相不受影响
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      div{
          width: 100px;
          height: 100px;
          background: yellowgreen;
          margin: 100px;
      }
    </style>
  </head>
  <body>
    <div></div>
    <div></div>
  </body>
</html>

image.png

现在我们给其中一个div创建BFC新的环境。

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      div{
          width: 100px;
          height: 100px;
          background: yellowgreen;
          margin: 100px;
          overflow: hidden;
          display: inline-block;
      }
    </style>
  </head>
  <body>
    <div></div>
    <div></div>
  </body>
</html>

image.png

例子2:BFC高度计算包含浮动元素

  • 计算BFC的高度时,考虑BFC所包含的所有子元素,连浮动元素也要参与计算。
  • 当元素不是BFC的子元素时,浮动元素高度不参与BFC计算(常见的盒子塌陷问题)
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .parent {
        background: gray;
      }

      .child {
          float: left;
          width: 100px;
          height: 100px;
          background: yellowgreen;
          margin: 100px;
      }
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="child"></div>
    </div>
  </body>
</html>

image.png

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .parent {
        background: gray;
        overflow: visible;
      }

      .child {
          float: left;
          width: 100px;
          height: 100px;
          background: yellowgreen;
          margin: 100px;
      }
    </style>
  </head>
  <body>
    <div class="parent">
      <div class="child"></div>
    </div>
  </body>
</html>

例子3:自适应两栏布局

  • 每个盒子(块盒与行盒)的margin box的左边,与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  • BFC的区域不会与float box重叠。
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .left {
        width: 100px;
        height: 150px;
        float: left;
        background: gray;
      }

      .right {
        height: 300px;
        background: rgb(170, 54, 236);
        background: yellowgreen;
      }
    </style>
  </head>
  <body>
    <div class="left">LEFT</div>
    <div class="right">RIGHT</div>
  </body>
</html>

image.png

<html lang="en">
  <head>
    <meta charset="UTF-8">
    <title>Document</title>
    <style>
      .left {
        width: 100px;
        height: 150px;
        float: left;
        background: gray;
      }

      .right {
        overflow: hidden;
        height: 300px;
        background: rgb(170, 54, 236);
        background: yellowgreen;
      }
    </style>
  </head>
  <body>
    <div class="left">LEFT</div>
    <div class="right">RIGHT</div>
  </body>
</html>

image.png

BFC总结

BFC就是页面上的一个隔离的独立容器,里外互相不受影响

整体的思路就是在现有的html BFC环境下,为了处理一些问题,触发BFC条件,生成新的BFC环境。来以此隔离解决原有的一些问题。

作者相关知识精选
  • chrome 106版本之后,支持对某个容器的媒体查询:

    .a {
       container-type: inline-size;
    }
    
    .b {
       color: yellow;
    }
    
    @container (min-width: 400px) {
      .b {
         color: blue;
      }
    }
    
    
    查看更多
  • 除了通过eval函数还有另一种方式可以将字符串当初js代码运行 new Function('data','return data')(data) ` 签名第一个是传参,后面的字符串是代码

    查看更多
  • 一个忽略的点

    svg文件不能以文件路径的形式放置在 img标签的src里面,这样是不会显示出来的

    因为svg的真正链接路径应该是svg里面的 xlink:href的路径,通常是以data:..., base64....开头的地址

    查看更多