关于BFC我想说这些

496 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第一天,点击查看活动详情

什么是BFC?

要想知道BFC,先得知道什么是FC。

FC(Formatting Context)全称格式化上下文,是W3C CSS2.1规范中的一个概念,它是页面中的一块渲染区域,并且有一套渲染的规则,FC规定了子元素如何定位,以及其他元素的关系和相互作用。元素在标准流当中时,必然是在某个FC中布局的

微信图片_20220505130442.png

这里贴出官方文档里的一段话,并且可以看到,块级盒子是在block formatting context中布局的,行内级的盒子是在inline formatting context中布局的。

那我们在这里就可以简单理解一下BFC,它是为在标准流中的块级盒子做布局用的。 或者说,BFC为块级元素的布局创造了一个单独的环境。

CSS2.1中只有BFC和IFC,CSS3后才有GFC和FFC,每一个不同的FC都有一套自己的渲染规则。

  • BFC(Block Formatting Context)块级格式化上下文
  • IFC(Inline Formatting Context)行内级格式化上下文
  • GFC(Grid Formatting Context)网格/栅格格式化上下文
  • FFC(Flex Foramtting Contex)弹性格式化上下文

BFC在哪呢?怎么才能触发BFC呢?

这里我把MDN上为我们提供的可以创建BFC的方式拿过来:

微信图片_20220505133834.png

BFC有什么用?带来了什么影响?

我们都知道,如果在页面上有一个宽高都为100px的盒子,那么默认情况下它会顶到页面的最左上角。那它凭什么就是顶到页面的左上角呢?凭什么不是在中间,又凭什么不能在页面的右下角呢? image.png 原来,这一切的一切,都是因为BFC的作用,我们来看看官方文档对BFC作用的描述

微信图片_20220505131921.png

简单翻译一下这两段话:在一个BFC的垂直方向上,盒子总是从包含块的最顶部一个紧挨着一个排布。垂直方向上相邻的两个盒子的距离是由margin属性决定的。并且,在同一个BFC中,两个相邻的块级盒子在垂直方向上的margin将会被折叠。

在一个BFC中,一个盒子的最左侧总是紧挨着包含块的最左侧(对于从右到左的格式,盒子的最右侧会紧挨着包含块的最右侧)。这个规则总是成立的,即便是在有浮动的情况下(尽管一个盒子可能会因为浮动而收缩),除非这个盒子是在一个新的BFC中(在这种情况下,由于浮动,盒子本身可能变得更窄)。 (PS:英语水平一般,翻的不好,大佬们勿喷,大家伙能理解这个意思就行)

好了,有了官方文档的这两段话,我们就可以解释为什么这个盒子会顶到左上角了,因为块级盒子在BFC中总是从包含块的顶部一个挨着一个往下排布的,并且盒子的最左侧会顶到包含块的最左侧,那不就得在左上角嘛。

解决margin折叠问题

细心的朋友们已经发现了,文档里对同一个BFC中块级盒子上下margin会折叠已经说的很清楚,为什么会折叠?就是BFC导致的!!!那怎么解决?这样看来就很简单了,我让你两不在同一个BFC中不就行了?so easy了对吧

先为大伙们演示下问题,下面两个盒子的间距应该是上面的margin-bottom+下面的margin-top=100px,但是可以很明显的看到实际效果是被折叠后只有50px。

<head>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .box1 {
      width: 100px;
      height: 100px;
      margin-bottom: 50px;
      background-color: #bfa;
    }
    .box2 {
      width: 100px;
      height: 100px;
      margin-top: 50px;
      background-color: aqua;
    }
  </style>
</head>
<body>
  <div class="box1"></div>
  <div class="box2"></div>
</body>

image.png 解决方案:只要能满足这两个盒子不在同一个BFC的方案都行。我这里就给其中一个盒子套一个父级容器,然后触发BFC,让这两个盒子不在同一个BFC就行。

  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .box-wrap {
      overflow: auto;
    }
    .box1 {
      width: 100px;
      height: 100px;
      margin-bottom: 50px;
      background-color: #bfa;
    }
    .box2 {
      width: 100px;
      height: 100px;
      margin-top: 50px;
      background-color: aqua;
    }
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box1"></div>
  </div>
  <div class="box2"></div>
</body>

image.png 好的,那么这个由BFC导致的问题,最终也由BFC解决了。舒服了。

解决浮动高度塌陷问题而不能解决绝对定位高度塌陷问题

我们都知道,浮动元素其实是脱离了标准流的,而BFC实际上是针对于标准流中块级元素的布局而言的,那么凭什么BFC能够去解决浮动元素导致的高度塌陷问题呢?话不多说,直接上文档:

image.png

这段太长了,我就不一句句翻译了,大家只需要看标题和最后两段话就行了。标题大家可以理解为:高度为“auto”的BFC的计算方式

倒数第二段话的意思是:绝对定位的子元素将被忽略。

最后一段话的意思是:如果有BFC里有浮动元素,那么会增加BFC的高度以包括这些浮动元素的下边缘

说白了,如果浮动元素是在BFC里,并且这个BFC的高度值为auto,那么BFC会自动长高直到能包裹住浮动元素为止。

看完这两段话,大伙们也可以理解,为什么**浮动和绝对定位同样都是脱离标准流导致父元素高度塌陷问题,BFC只能解决浮动的高度塌陷,而不能解决绝对定位导致的高度塌陷问题。**文档里说的非常清晰了。

理解了这个原理,那解决浮动的高度塌陷的问题就很简单了。给浮动元素的父元素开启BFC不就行了嘛。 我这里还是给大伙们演示一下哈。

<head>
  <title>Document</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .box-wrap {
      background-color: aqua;
    }
    .box {
      width: 100px;
      height: 100px;
      background-color: #bfa;
    }
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box"></div>
  </div>
</body>

image.png

<head>
  <title>Document</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .box-wrap {
      background-color: aqua;
    }
    .box {
      float: left;
      width: 100px;
      height: 100px;
      background-color: #bfa;
    }
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box"></div>
  </div>
</body>

image.png

<head>
  <title>Document</title>
  <style>
    body {
      margin: 0;
      padding: 0;
    }
    .box-wrap {
      background-color: aqua;
      overflow: auto;
    }
    .box {
      float: left;
      width: 100px;
      height: 100px;
      background-color: #bfa;
    }
  </style>
</head>
<body>
  <div class="box-wrap">
    <div class="box"></div>
  </div>
</body>

image.png

总结

其实BFC就是在标准流里为块级盒子布局提供了一个环境,这个环境里的子元素不会影响到环境外的其他元素,也不会受外部元素的影响。这个环境里有它自己的一些特定规则,比如块级盒子上下的外边距折叠,比如高度为auto时的高度计算方式等等,理解了这些本质,再看BFC就非常的清晰易懂啦。