BFC的形成和排版规则

何为bfc?

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

如何产生bfc?

浮动元素、绝对定位元素,不是块级盒的块级包含块(比如inline-block、table-cell、table-capation)和overflow值不为visible的块级盒子为它们的内容建立了一个新的块级排版上下文。

 

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

bfc排版规则

在一个块级排版上下文中,盒子是从包含块顶部开始,垂直的一个接一个的排列的,相邻两个盒子之间的垂直的间距是被margin属性所决定的,在一个块级排版上下文中相邻的两个块级盒之间的垂直margin是折叠的。参与BFC的布局的只有普通流normal flow中的块级盒,而float、position值不为relative\static的元素是脱离BFC这一布局环境的,不参与BFC的布局.

在一个块级排版上下文中,每个盒子的左外边是触碰到包含块的左边的(对于从右向左的排版,则相反),即使在有浮动元素参与的情况下也是如此(即使一个盒子的行盒是因为浮动而收缩了的),除非这个盒子新建了一个块级排版上下文(在某些情况下这个盒子自身会因为floats而变窄)

 

bfc约束条件

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

bfc约束条件

  1. 不和浮动元素重叠

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

<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的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。

 

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

BFC的区域不会与float box重叠

.main {
    overflow: hidden;
}

  

我们可以通过通过触发main生成BFC, 来实现自适应两栏布局

 

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

 

 

 

 

  1. 清除元素内部浮动
<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
}

  

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

 

 

  1.  防止垂直 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内部:

水平方向: 每个盒子的左外边是触碰到包含块的左边(从右向左与此相反)
垂直方向: 在一个块级排版上下文中,盒子是从包含块顶部开始,垂直的一个接一个的排列的; 垂直距离由相邻的margin值决定(相等的话会重叠),不相等的话由最大的margin决定(注意也会重叠)

bfc之间:

不同的bfc之间内部的元素不会相互影响,bfc像一个坚固的墙,将不同的bfc隔离开,每一个bfc之间遵循bfc布局规则

 

 

注: 以上为本人在网上查找资料提取的,详情请访问 http://web.jobbole.com/84808/

参考:什么是BFC?(https://juejin.cn/post/6844903544726749198)

posted @ 2018-01-11 20:12  韩帅  阅读(330)  评论(0编辑  收藏  举报