BFC究竟是什么?

350 阅读4分钟

BFC究竟是什么

来看一下MDN上给出的定义:

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

想要直接通过这句定义看明白BFC的意义,或者说作用,那可以说是相当的困难。

我来说一个我的理解:BFC就是一个盒子,这个盒子里的子元素脱离了外面的文本流,只和它的父元素产生关系,并且一定会产生关系,当然我的理解也不是那么容易能直接理解到位,因此我们来深入探究一下BFC。

创建BFC的方法

先不管BFC究竟是什么,以及BFC的作用,我们来看看如何创建BFC,读者也可以先略过这一部分,当彻底明白BFC后,再回过头来看如何创建BFC也无妨。

  1. 根元素
  2. 浮动元素(元素的float不是none)
  3. 绝对定位元素
  4. display取 inline-block、table-cell、table、flow-root、flex、grid元素
  5. contain取layout,content,paint
  6. overflow取不为visible的块元素。

这些方法都能创建出来BFC。

BFC的作用究竟是什么?

毫无疑问这应该是读者最关心的重点,直接下结论:

  1. 清除内部浮动
  2. 垂直margin合并
  3. 创建自适应两栏布局

清除内部浮动

我们都知道浮动布局会脱离文本流,在父元素下的子元素如果设定了float布局,代码如下:

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .flow{
      width: 100px;
      height: 100px;
      background: lightblue;
      margin: 100px;
      float: left;
    }
    .father{
    }
  </style>

  <head>
    <body>
      <div class="father">
        <div class="flow"></div>
      </div>
    </body>
</html>

由于子元素脱离了文本流,那么父元素就没有了子节点,如果说高度没有设定的话,那么就是auto,自动设为了0。

如下图所示

在本例当中,似乎不影响什么,但是在某些时候还是希望float的元素能够撑开父节点的,那么该如何做呢?那就是用BFC,将父节点变为一个BFC盒子,子元素的浮动就会撑开父元素了。

直接在父元素上加如下样式

.father{
      overflow: hidden;
}

这样一来,父元素变被撑开了。

垂直magin合并

来看这么一段代码

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .box{
      width: 100px;
      height: 100px;
      background: lightblue;
      margin: 100px;
    }
  </style>

  <head>
    <body>
      <div class="box"></div>
      <div class="box"></div>
    </body>
</html>

效果如下图所示

能明显看出来,margin只有100了,也就是所谓的外边距被合并了,原因就是

块的上外边距(margin-top)和下外边距(margin-bottom)有时合并(折叠)为单个边距,其大小为单个边距的最大值(或如果它们相等,则仅为其中一个),这种行为称为边距折叠

如何解决边距折叠这个常见现象呢?就要利用到BFC了。

上文说过,BFC的效果是创建一个盒子,盒子里的子元素只会与父元素产生关系,且这个关系一定会存在。

那也就是说,盒子里的子元素设置边距,那一定是相对于父元素,也就是这个相对于创建出来的BFC盒子的边距,它是不会被边距折叠的。

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    .box{
      width: 100px;
      height: 100px;
      background: lightblue;
      margin: 100px;
      overflow: hidden;
    }
  </style>

  <head>
    <body>
      <div class="box"></div>
      <div style="overflow: auto;">
        <div class="box"></div>
      </div>
    </body>
</html>

如上面的代码所示,我们就是创建了一个新的div包裹了下面的div,这个div我们加了一个样式overflow:auto,聪明的你已经发现了,这个是属于一开始创建BFC的方法之一的,因此我们创建了一个BFC盒子div,在这个div里magin-top是相对于这个盒子所处的位置,因此如下图所示,解决了这个问题:

创建自适应两栏布局

我们经常会有以下的需求,一列图片,一列文字,如果直接采取下面的方式

<!DOCTYPE html>
<html lang="en">

<head>
  <style>
    div {
      width: 200px;
    }
    img{
      float: left ;
    }
  </style>

  <head>
    <body>
      <div>
        <img src="https://lf3-cdn-tos.bytescm.com/obj/static/xitu_juejin_web/e08da34488b114bd4c665ba2fa520a31.svg"></img>
        <p class="info">这边是我们需要的文字排版</p>
      </div>

    </body>
</html>

会是一个环绕图片型的文字排版,原因是float脱离了文本流,p占据了整个行,那么当超过width时候自然会放到图片下面了。

我们如果要写一个两栏布局的话,就需要让p元素不影响浮动元素。

因此将p写为BFC元素。

添加样式:

p{overflow: auto}

两栏布局也就成功了。

总结

BFC随着flex布局的流行,自然而然的会使用的相对少了些,因为当你设置flex时候会自动有BFC,以及flex布局的强大功能。但是如果我们知道了BFC的原理,以及如何创建,那么在某些时候就能够解释CSS的奇怪现象了。