BFC的定义
是 W3C CSS 2.1 规范中的一个概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。
在创建了 Block Formatting Context 的元素中,其子元素会一个接一个地放置。垂直方向上他们的起点是一个包含块的顶部,两个相邻的元素之间的垂直距离取决于 ‘margin’ 特性。在 Block Formatting Context 中相邻的块级元素的垂直边距会折叠(collapse)。
在 Block Formatting Context 中,每一个元素左外边与包含块的左边相接触(对于从右到左的格式化,右外边接触右边), 即使存在浮动也是如此(尽管一个元素的内容区域会由于浮动而压缩),除非这个元素也创建了一个新的 Block Formatting Context 。
example:
<div class="con">
<img class="himg floatLeft" src="mm.jpg" /><div class="mainCon">many text and pic here</div>
</div>
~~~ .himg 和 div.mainCon的左外边框是与div.con左边框接触的,当div.mainCon内容较多时,表现为围绕浮动的.himg元素,触发div.mainCon元素的BFC即避免围绕浮动元素,从而实现2列布局
触发元素的BFC的方式:
1.设置浮动 则div.mainCon的宽度会自适应内容多少,div.con剩余宽度不够容纳div.mainCon的内容时会出现换行,要确保2列布局需要指定div.mainCon的宽度
2.设置overflow:hidden; 2列布局,div.mainCon自适应容器剩余宽度,但设置溢出隐藏,限制了不能在div.mainCon外布局其他元素(如 箭头 浮动菜单...),
注意(设置 overflow:hidden; 或 overflow:auto; 元素都是隐藏溢出的 test in chrome)
3.display:inline-block 或 display:table-caption 效果同float, div.mainCon 宽度自适应内容多少 内容多会换行,要设定宽度才能确保2列布局
4.display:table-cell 效果同float ,宽度自适应内容多少 内容多不会换行,不用设定宽度确保2列布局,确定 ie6-7不支持display:table-cell
5.position:absolute; 效果同 display:table-cell, 兼容性好一点
当涉及到可视化布局的时候,Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局。比如浮动元素会形成BFC,浮动元素内部子元素的主要受该浮动元素影响,两个浮动元素之间是互不影响的。这里有点类似一个BFC就是一个独立的行政单位的意思。
如果一个浮动元素后面跟着一个非浮动的元素,那么就会产生一个覆盖的现象,很多自适应的两栏布局就是这么做的。比如下图的效果,参考例子
<div style="float:left; border: 2px solid red"> 123</div> <p style="border: 2px solid blue;display:block;overflow:hidden;*zoom:1"> The quick brown fox jumped over the 4seohunt.com lazy dog's back. The quick brown fox jumped over the lazy dog's back. The quick brown fox jumped over the lazy dog's back. The quick brown fox jumped over the lazy dog's back. The quick brown fox jumped over the lazy dog's back. </p>
只要把父元素设为BFC就可以清理子元素的浮动影响(即父元素的高度塌陷)了,最常见的用法就是在父元素上设置overflow: hidden样式,对于IE6加上zoom:1就可以了(IE Haslayout)。
按照BFC的定义,只有同属于一个BFC时,两个元素才有可能发生垂直Margin的重叠,这个包括相邻元素,嵌套元素,只要他们之间没有阻挡(例如边框,非空内容,padding等)就会发生margin重叠。
因此要解决margin重叠问题,只要让它们不在同一个BFC就行了,但是对于两个相邻元素来说,意义不大,没有必要给它们加个外壳,但是对于嵌套元素来说就很有必要了,只要把父元素设为BFC就可以了。这样子元素的margin就不会和父元素的margin发生重叠了。
<div class="prev">prev div</div>
<div class="next mt10 h100 bg-darkred"><h2 class="mt100 h10 bg-darkblue">i am title</h2></div>
div.pre 和 div.next的垂直间距为100px; 因为 div.next 和它内部的h2属于同一个BFC,所以垂直margin重叠了(h2的垂直margin川穿透了父元素 影响了父元素和其他元素的关系),
解决方法:
1.让2个margin-top不相邻(div.next的margin-top:10px 和 h2的margin-top:100px),设置父元素的border 或padding
2.触发父元素的BFC, 形成独立的布局单元