Block Formatting Context(块级格式化上下文)是W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其余元素的关系和相互做用。浏览器
简单来说,咱们能够把它理解为,咱们在进行盒模型布局的时候,若是一个元素符合了成为BFC的条件,该元素成为一个隔离了的独立容器,元素内部元素会垂直的沿着其父元素的边框排列,和外部元素互不影响 。好比浮动元素会触发BFC,浮动元素内部的子元素主要受到该浮动元素的影响,而两个浮动元素之间是互不影响的。布局
在CSS3 中,BFC 叫作Flow Root。在早期的ie中也有相似的概念haslayout IE六、7的不少布局产生的bug(如3px间隙、绝对定位的继承宽度)均可以经过触发hasLayout修复,比较推荐的方法为zoom:1与height:1%,不会破坏已有的样式,相信你们对它并不陌生。spa
一样的以往集中在float、绝对定位、margin collaspe中的不少困惑,在理解了bfc后,都可以被咱们一一解除 。.net
w3c规范对BFC的解释:
浮动元素和绝对定位元素,不是块级盒子的块容器 (如 inline-blocks, table-cells, 和 table-captions),以及设置了overflow属性(除了visible)的块级盒子 ,都会为他们的内容建立新的BFC(块级格式上下文)。
在BFC中,盒子从顶端开始垂直地 一个接一个地排列,两个盒子之间的垂直的间隙是由他们的margin 值所决定的。在一个BFC中,两个相邻的块级盒子的垂直外边距会产生折叠。
在BFC中,每个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来讲,则触碰到右边缘)。code
float 元素
position(absolute,fixed)
display (table-cell,table-caption,inline-block)
overflow 除了visible 之外的值(hidden,auto,scroll )
fieldset元素
早期IE的hasLayout会触发一个新的block formatting contextorm
BFC的特性cdn
第一个特性特别有用,由于元素触发了BFC的话,就不会被float元素覆盖,当子元素所有浮动的时候也可以正确地包含了
第二个margin不会叠加的特性,能够理解为两个处于普通流的盒子,会有margin叠加的问题,是由于他们属于相同的BFC,当他自身建立了一个新的BFC时,这个问题就不存在了blog
1.经过边缘不和浮动元素重叠的特性,实现两栏结构。继承
若是一个浮动元素后面跟着一个非浮动的元素,那么就会产生一个覆盖的现象,经过触发BFC来清除覆盖,不少自适应的两栏布局就是这么作的。
下面咱们来看左边图片+右边信息的示例:图片
// CSS div,p{margin:0;padding:0;} .box {width:320px;} .img {width: 80px;height: 80px;margin-right:10px;float:left;} .info {background: #ff9;color: #404040;} // HTML <div class="box"> <div class="img"><img src="http://wwc.taobaocdn.com/avatar/getAvatar.do?userNick=feihu2987&width=80&height=80&type=sns" width="80" height="80" alt="头像"></div> <p class="info">风吹亮雪花,吹白咱们的头发,当初说一块儿闯天下,大家还记得吗?</p> </div>
通常状况下它呈现出咱们所乐意看到的样子:
但随着文字信息增多后,会变地很是的糟糕:
很明显,这是由于info类里面的文字受到了浮动元素的影响,但这并非咱们所指望的。此时咱们能够为P元素的内容创建一个BFC,让其内容消除对外界浮动元素的影响。根据上文所知,只要给info元素添加overflow:hidden;便可为其内容创建新的BFC。固然你也能够经过其余方法来创建。其效果以下:
至此,咱们能够抛弃计算设置左边边距,或是设置右边浮动再清除父元素的浮动这些弱爆的方式了。
demo地址: http://jsfiddle.net/k9u5x/
固然考虑到ie6 7 的兼容性,咱们同时触发一下 haslayout就再好不过了,更多示例请看豆瓣小组和阅读中,不少地方使用了此方式:
http://www.douban.com/group/explore/culture
.channel-item .bd, .channel-item .block,.channel-item .block p, .mod .hd, .channel-group-rec li, .channel-group-rec li .info { overflow: hidden; zoom: 1; }
2.清除元素内部浮动
只要把父元素设为BFC就能够清理子元素的浮动了,一样的由于IE6-7不支持BFC,所以要设置zoom:1来触发hasLayout 闭合浮动。
咱们最多见的兼容用法就是在父元素上添加class clearfix ;
.clearfix {*zoom:1} .clearfix:after{content:"\0020";display:block;height:0;clear:both;visibility:hidden}
3.解决合并外边距的问题
在CSS当中,相邻的两个盒子(多是兄弟关系也多是父子关系)的外边距能够结合成一个单独的外边距。这种合并外边距的方式被称为折叠,而且于是所结合成的外边距称为折叠外边距。
按照BFC的定义,只有同属于一个BFC时,两个元素才有可能发生垂直Margin的重叠,这个包括相邻元素,嵌套元素,只要他们之间没有线盒(其实就是非空内容),没有间隙(clearance,设置clear以闭合相关方向的浮动 ),没有padding和border将他们分隔开就会发生margin重叠。
所以要解决margin重叠问题,只要让它们不在同一个BFC就好了,可是对于两个相邻元素来讲,意义不大,没有必要给它们加个外壳,可是对于嵌套元素来讲就颇有必要了,只要把父元素设为BFC就能够了。这样子元素的margin就不会和父元素的margin发生折叠了。
折叠的结果:
两个相邻的外边距都是正数时,折叠结果是它们二者之间较大的值( 10px 20px 结果为20px )。
两个相邻的外边距都是负数时,折叠结果是二者绝对值较大的值( -10px -20px 结果是-20px )。
两个外边距一正一负时,折叠结果是二者的相加的和( 10px -20px 结果是10px )。
产生折叠的必备条件:margin必须是边缘毗邻的
而根据w3c规范,两个margin是垂直毗邻的必须知足如下条件:
元素的margin-top与其第一个常规文档流的子元素的margin-top
元素的margin-bottom与其下一个常规文档流的兄弟元素的margin-top
height为auto的元素的margin-bottom与其最后一个常规文档流的子元素的margin-bottom
高度为0而且最小高度也为0,不包含常规文档流的子元素,而且自身没有创建新的BFC的元素的margin-top和margin-bottom
只要触发Block Formatting Contexts的条件 或者是使用非空内容,空隙(clearance),padding和border将他们分隔开margin便不会折叠。
分析一:浮动和绝对定位不与任何元素产生 margin 折叠
缘由:浮动元素和绝对定位元素不与其余盒子产生外边距折叠是由于元素会脱离当前的文档流,违反了上面所述的两个margin是邻接的条件同时,又由于浮动和绝对定位会使元素为它的内容建立新的BFC,所以该元素和子元素所处的BFC是不相同的,所以也不会产生margin的折叠。
分析二:inline-block元素与其兄弟元素、子元素和父元素的外边距都不会折叠(包括其父元素和子元素)
inline-block不符合w3c规范所说元素必须是块级盒子的条件,由于规范中又说明,块级盒子的display属性必须是如下三种之一:'block', 'list-item', 和 'table'。
分析三:设置有些属性(如float、position、display)会同时造成BFC与触发hasLayout,或者在>=IE7时也能够设置overflow同时搞定二者。
在IE7如下,只触发(造成)了其中一个,也最好同时触发(造成)另外一个,以保证浏览器的兼容。
简单的触发方法:{overflow: hidden;zoom:1;}
若是感受阅读此文后,有必定的启发和收获,劳驾您推荐下,在此谢过,欢迎留言交流。