什么是BFC?

前言

对于BFC的概念以及应用场景一直都不是很明白,今天着重去了解了一下,作了如下总结。css

BFC的定义

在解释 BFC 是什么以前,须要先介绍 Box、Formatting Context的概念。css3

Box: CSS布局的基本单位

  Box 是 CSS 布局的对象和基本单位, 直观点来讲,就是一个页面是由不少个 Box 组成的。元素的类型和 display 属性,决定了这个 Box 的类型。 不一样类型的 Box, 会参与不一样的 Formatting Context(一个决定如何渲染文档的容器),所以Box内的元素会以不一样的方式渲染。让咱们看看有哪些盒子: block-level box:display 属性为 block, list-item, table 的元素,会生成 block-level box。而且参与 block fomatting context; inline-level box:display 属性为 inline, inline-block, inline-table 的元素,会生成 inline-level box。而且参与 inline formatting context; run-in box: css3 中才有, 这儿先不讲了。git

Formatting context

  Formatting context 是 W3C CSS2.1 规范中的一个概念。它是页面中的一块渲染区域,而且有一套渲染规则,它决定了其子元素将如何定位,以及和其余元素的关系和相互做用。最多见的 Formatting context 有 Block fomatting context (简称BFC)和 Inline formatting context (简称IFC)。 CSS2.1 中只有 BFC 和 IFC, CSS3 中还增长了 GFC 和 FFC。bash

BFC

  BFC(Block Formatting Context)直译为“块级格式化范围”。是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其余元素的关系和相互做用 当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照必定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。好比浮动元素会造成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点相似一个BFC就是一个独立的行政单位的意思。 也能够说BFC就是一个做用范围。能够把它理解成是一个独立的容器,而且这个容器的里box的布局,与这个容器外的绝不相干ide

怎样才能造成BFC

  1. float的值不能为none
  2. overflow的值不能为visible
  3. display的值为table-cell, table-caption, inline-block中的任何一个
  4. position的值不为relative和static 

BFC的约束规则

  1. 内部的Box会在垂直方向上一个接一个的放置
  2. 垂直方向的距离有margin决定(属于同一个BFC的两个相邻Box的margin会发生重叠,与方向无关)
  3. 每一个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此
  4. BFC的区域不会与float的元素区域重叠
  5. 计算BFC的高度时,浮动子元素也参与计算
  6. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然

看到以上的几条约束,让我想起学习css时的几条规则布局

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

BFC的做用

1. 不和浮动元素重叠

若是一个浮动元素后面跟着一个非浮动的元素,那么就会产生一个覆盖的现象,不少自适应的两栏布局就是这么作的。好比下图的效果,参考例子ui

<style>
    body {
        width: 300px;
        position: relative;
    }

    .aside {
        width: 100px;
        height: 150px;
        float: left;
        background: #f66;
    }

    .main {
        height: 200px;
        background: #fcc;
    }
</style>
<body>
    <div class="aside"></div>
    <div class="main"></div>
</body>
复制代码

案例分析: 很明显,.aside和.mian重叠了。试分析一下,因为两个box都处在同一个BFC中,都是以BFC边界为起点,若是两个box自己都具有BFC的话,会按顺序一个一个排列布局,如今.main并不具有BFC,根据BFC布局规则第3条

每一个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,不然相反)。即便存在浮动也是如此。spa

虽然存在浮动的元素aslide,但main的左边依然会与包含块的左边相接触 根据BFC布局规则第四条:3d

BFC的区域不会与float box重叠

咱们能够经过经过触发main生成BFC, 来实现自适应两栏布局

.main {
    overflow: hidden;
}
复制代码

当触发main生成BFC后,这个新的BFC不会与浮动的aside重叠。所以会根据包含块的宽度,和aside的宽度,自动变窄。效果以下:

2. 清除元素内部浮动

案例代码:

<style>
    .par {
        border: 5px solid #fcc;
        width: 300px;
    }

    .child {
        border: 5px solid #f66;
        width:100px;
        height: 100px;
        float: left;
    }
</style>
<body>
    <div class="par">
        <div class="child"></div>
        <div class="child"></div>
    </div>
</body>
复制代码

根据BFC布局规则第六条:

计算BFC的高度时,浮动元素也参与计算

为达到清除内部浮动,咱们能够触发par生成BFC,那么par在计算高度时,par内部的浮动元素child也会参与计算。

.par{
  overflow:hidden
}
复制代码

加入上面样式,便可解决问题,效果以下:

3. 防止垂直 margin 重叠
<style>
    p {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
</style>
<body>
    <p>Haha</p>
    <p>Hehe</p>
</body>
复制代码

页面以下:

两个p之间的距离为100px,发送了margin重叠。根据BFC布局规则第二条:

Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠

咱们能够在p外面包裹一层容器,并触发该容器生成一个BFC。那么两个P便不属于同一个BFC,就不会发生margin重叠了。

<style>
    .wrap {
        overflow: hidden;
    }
    p {
        color: #f55;
        background: #fcc;
        width: 200px;
        line-height: 100px;
        text-align:center;
        margin: 100px;
    }
</style>
<body>
    <p>Haha</p>
    <div class="wrap">
        <p>Hehe</p>
    </div>
</body>
复制代码

效果以下:

按照BFC的定义,只有同属于一个BFC时,两个元素才有可能发生垂直Margin的重叠,这个包括相邻元素,嵌套元素,只要他们之间没有阻挡(例如边框,非空内容,padding等)就会发生margin重叠。 所以要解决margin重叠问题,只要让它们不在同一个BFC就好了,可是对于两个相邻元素来讲,意义不大,没有必要给它们加个外壳,可是对于嵌套元素来讲就颇有必要了,只要把父元素设为BFC就能够了。这样子元素的margin就不会和父元素的margin发生重叠了。

部份内容来自BFC背后神奇的原理

相关文章
相关标签/搜索