代码改变世界

css Block formatting context BFC

2013-09-29 05:51  youxin  阅读(735)  评论(0编辑  收藏  举报

w3c关于BFC解释:

http://www.w3.org/TR/CSS21/visuren.html#block-formatting

Mdn描述:

block formatting context is a part of a visual CSS rendering of a Web page. It is the region in which the layout of block boxes occurs and in which floats interact with each other.

A block formatting context is created by one of the following:

  • the root element or something that contains it
  • floats (elements where float is not none)
  • absolutely positioned elements (elements where position is absolute or fixed)
  • inline-blocks (elements with display: inline-block)
  • table cells (elements with display: table-cell, which is the default for HTML table cells)
  • table captions (elements with display: table-caption, which is the default for HTML table captions)
  • elements where overflow has a value other than visible
  • flex boxes (elements with display: flex or inline-flex)

从上可以看到,display设置为inline-block,table-cell,table-caption,flex,inline-flex可以建立一个BFC。

 

A block formatting context contains everything inside of the element creating it that is not also inside a descendant element that creates a new block formatting context.

Block formatting contexts are important for the positioning (see float) and clearing (see clear) of floats. The rules for positioning and clearing of floats apply only to things within the same block formatting context. Floats do not affect the layout of things in other block formatting contexts, and clear only clears past floats in the same block formatting context.

--------------------------------

首先根元素可以产生独立的BFC,然后是设置float的元素(除float值为none),position定位元素只满足两个absolute和fixed,所以relative和static都不行(要注意IE下position为relative是可以触发haslayout的)。此外设置了display:inline-block的元素可以,设置了display:table-cell的元素。设置了display:table-caption。设置了overflow,除值为visible的情况(auto,hidden,scroll都可以)。

那BFC究竟干嘛用的:

一般情况下,两个上下相邻的盒子会折叠它们垂直方向的外边距,但这种情况只发生在同一个Block Formatting Context中。换句话说,在同一个布局环境中(Block Formatting Context)是边距折叠的必要条件。这也就是为什么浮动的元素和绝对定位元素不会发生边距折叠的原因(因为它们设置了浮动,设置了定位,所以它们形成了独立的BFC,所以边距折叠的情况就不会发生),同一个BFC环境很重要,因为如果是不同的BFC,很多我们固有意识中的现象不会再发生。

以下是一篇到底bfc是否可以阻止折叠margin的争论:

http://www.zhihu.com/question/19823139

 

BFC:Block Formatting Context.

BFC就是一种布局方式,在这种布局方式下,盒子们自所在的 containing block 顶部起一个接一个垂直排列,水平方向上撑满整个宽度 (除非内部的盒子自己内部建立了新的 BFC)。 developer center上面有对BFC的一段描述:
一个 block formatting context 是web页面可视化CSS渲染的一个部分,是一块 block boxes 排布以及 float 元素相互作用的区域。

可以理解为一个作用范围,在一个BFC里的布局与其之外的布局不相关或者说不相互影响。有一个形象的例子可作参考:

把一个页面想象成大的集装箱,这个集装箱里装的货物就是HTML元素。在现实生活中为了避免不同人的货物相互混淆,都是把 货物打好包装再装入集装箱,这样的话无论你包装里面的货物怎么摆放,都不会影响到其他人的货物。那么这个包装就可以被想象成Block Formatting Context。

如何创建BFC

当一个HTML元素满足下面条件的任何一点,都可以产生Block Formatting Context:

  • float的值不为”none”
  • overflow的值不为”visible”
  • display的值为 “table-cell”, “table-caption”, or “inline-block”中的任何一个
  • position的值不为 “static” 或 “relative”中的任何一个

我是一个使用浮动布局的孩子来的。今天才知道了这种原来也有可以不用清除浮动来布局,只要对BFC这个概念清晰明了,完全可以不用清除浮动来布局了。

以前的误解

1.折叠margin

以前总是认为,相邻两个盒子放在一起,他们的margin会重叠,取值为最大的一个作为他们之间的margin值

下面我在一篇文章里面彻底了解了折叠margin产生的原因了。

些margin都处于普通流中,并在同一个BFC中;
这些margin没有被非空内容、padding、border 或 clear 分隔开;
这些margin在垂直方向上是毗邻的,包括以下几种情况:

1、一个box的top margin与第一个子box的top margin
2、一个box的bottom margin与最后一个子box的bottom margin,但须在该box的height为auto的情况下
3、一个box的bottom margin与紧接着的下一个box的top margin
4、一个box的top margin与其自身的bottom margin,但须满足没创建BFC、零min-height、零或者“auto”的height、没有普通流的子box

垂直方向上毗邻的box不会发生折叠的情况:

根元素的外边距不会参与折叠

一个有clearance的box的上下margin毗邻,它会与紧接着的下一个box发生margin折叠,但折叠后的margin不会再与它们父box的bottom margin折叠

折叠边距的计算

当两个margin都是正值的时候,取两者的最大值;当 margin 都是负值的时候,取的是其中绝对值较大的,然后,从 0 位置,负向位移;当有正有负的时候,先取出负 margin 中绝对值中最大的,然后,和正 margin 值中最大的 margin 相加。但必须注意,所有毗邻的margin要一起参与运算,不能分步进行。

如何解决再float的情况下两个盒子折叠在一起呢?方法当然是建立一个bfc

<div style="background:#eee;border:1px solid red;overflow:hidden;">
<div id="A" style="background:#aaa;overflow:auto;margin-top:20px;">
<div id="B" style="background:white;border:1px solid green;margin-top:10px;">
  B:给A加了overflow:auto之后,我有10px的margin-top了
</div>
</div>
</div>
上面可以看到,想解决垂直边距叠加问题,关键就是给相对应的容器新建一个BFC。建立一个BFC来解决处于同一个盒子中的两个不同盒子分离出来

2.BFC可以包裹浮动元素实例解析

继续BFC的话题的讨论,本文讨论一个简单的例子:如何制作两行两列的网页布局,解决浮动布局不换行的问题。

制作两行两列的布局方法很多,浮动布局、表格布局和基于display:inline-block的列表布局。这个重点讨论浮动布局,因为我们这里要解决浮动布局里的一个问题:元素浮动不换行怎么办?其他布局先做简单叙述,作为拓展将在以后的博文里仔细论述。
用浮动布局实现

考虑一下下面的例子,目标是显示成两行两列:

<div id="A">
<div id="red" style="background: red;width: 100px;height: 100px;float: left;"></div>
<div id="orange" style="background: orange;width: 100px;height: 100px;float: left;"></div>
</div>
<div id="B">
<div id="yellow" style="background: yellow;width: 100px;height: 100px;float: left;"></div>
<div id="green" style="background: green;width: 100px;height: 100px;float: left;"></div>
</div>

我们可以看到四个盒子最终都处在一列里面。

但我们的本意是让他们处在同一个盒子,并分成两列的。

有什么方法呢?

在其中一个外层盒子建立一个BFC了

<div id="A" style="display:inline-block;">
<div id="red" style="background: red;width: 100px;height: 100px;float: left;"></div>
<div id="orange" style="background: orange;width: 100px;height: 100px;float: left;"></div>
</div>
<div id="B">
<div id="yellow" style="background: yellow;width: 100px;height: 100px;float: left;"></div>
<div id="green" style="background: green;width: 100px;height: 100px;float: left;"></div>
</div>
好了,终于实现两行两列的浮动布局了,明白了吗?就是BFC的作用:BFC可以包裹浮动元素

3.左边的浮动,右边的盒子被左边的遮住了

以前我一直以为是正常的,现在了解到BFC才了解到原来可以避免,以前一直是通过给右边添加padding-left或者margin-left来使之脱离了左边的遮罩。
现在才知道可以通过给右边建立新的BFC来使之在A的右边的。
代码可以为:
<div class="item">
<div class="img"></div>
<div class="content"></div>
</div>
css代码可以为
.img{float:left; margin-right:10px; }
.content{overflow:auto; zoom:1;}
 
(完整代码:
<div class="item">
<div class="img"></div>
<div class="content"></div>
</div>
 
.img{
    float:left;
    width:100px;
    height:100px;
    background-color:#ccc;
    
     
}
.content{ 
    background-color:green;
    width:500px;
    height:300px;
      overflow:auto;
}

  

 

4.层内浮动溢出的探讨

<div id="side" style="float:left">向左浮动元素</div>
<div id="content">
<div id="content-inner">
<ul class="content-banner clearfix">
<li class="item" style="float:left">向左浮动元素</li>
<li class="item" style="float:left">向左浮动元素</li>
<li class="item" style="float:left">向左浮动元素</li>
</ul>
</div>
</div>
这个问题实例中给ul的父级元素加一个:overflow:auto;*zoom:1就可以了(加浮动也可以或其他),即新建一个BFC,问题解决了。
 
本文示例来自这篇:BFC学习札记,非常感谢作者写出这么高质量的文章。
 
另外我这里也很喜欢他举出的几个例子和解决方法。希望日后可以发现更多相关BFC的内容。
 
 
 

 

更多:

看以前的:http://www.cnblogs.com/youxin/archive/2012/08/21/2649350.html

http://www.w3ctech.com/p/1101

http://www.cnblogs.com/pigtail/archive/2013/01/23/2871627.html

http://zenxds.info/bfc-%E5%9D%97%E6%A0%BC%E5%BC%8F%E5%8C%96%E4%B8%8A%E4%B8%8B%E6%96%87/