Block Formatting Context 能帮助我们做什么?
Block Formatting Context(块格式化上下文)是个很重要的概念,它决定了元素如何对其内容进行定位,以及与其他元素的关系和相互作用。
举个好理解的例子:可以把页面想象成一个社区,这个社区里的建筑就是 HTML 元素。而为了避免不同社区里的建筑相互混淆,开发商都是把建筑建在自己的社区里,这样的话无论开发商怎么盖楼,都不会影响到其它社区,那么这个社区的范围 就可以被想象成 Block Formatting Context。
由于在 IE8 之前的 IE 版本中,规范中没有提及 Block Formatting Context 的概念,而是用私有属性 hasLayout 来达到相似的目的。两者都是决定了对内容如何定位及大小计算的规则,以及与其它元素的相互作用的规则,但它们对一类事物的不同理解,以及它们的启用条件也 都不尽相同,所以很多兼容性的问题都是因它而起。
可生成 Block Formatting Context 的 CSS 特性:
- float: ( 除 none 外的任何值 )
- overflow: ( 除 visible 外的任何值 )
- display: ( table-cell,table-caption 或 inline-block )
- position: ( 除 relative 和 static 外任意值 )
可触发 hasLayout 的 CSS 特性:
- display: inline-block
- height: ( 除 auto 外任何值 )
- width: ( 除 auto 外任何值 )
- float: ( left 或 right )
- position: absolute
- writing-mode: tb-rl
- zoom: ( 除 normal 外任意值 )
目前最好的解决方案就是使元素即生成 Block Formatting Context,又触发 hasLayout。IE下通过设置“zoom:1”,便可触发 hasLayout。
好了,讲了这么多概念性的东西,我们来看看 Block Formatting Context 能在实际中帮我们解决什么问题:
1.防止文字环绕
.red, .orange, .yellow, .green { float:left; width:120px; height:120px; } .red { background:red; } .orange { background:orange; } .yellow { background:yellow; } .green { background:green; } .w_1, .w_2 { overflow:hidden; }
<div class="box"></div> <ul class="news-list"> <li>我是个测试数据,别管我 ^ ^</li> <li>我是个测试数据,别管我 ^ ^</li> <li>我是个测试数据,别管我 ^ ^</li> <li>我是个测试数据,别管我 ^ ^</li> <li>我是个测试数据,别管我 ^ ^</li> <li>我是个测试数据,别管我 ^ ^</li> </ul>
overflow 属性一旦被指定,那么一个新的 Block Formatting Context 就被创建了,它不再围绕浮动元素。
2.闭合浮动
.red, .orange, .yellow, .green { float:left; width:120px; height:120px; } .red { background:red; } .orange { background:orange; } .yellow { background:yellow; } .green { background:green; } .w_1, .w_2 { overflow:hidden; }
<div class="w_1"> <div class="red"></div> <div class="orange"></div> </div> <div class="w_2"> <div class="yellow"></div> <div class="green"></div> </div>
本来想由四个方块组成一个两行两列的布局,但是由于 .red, .orange, .yellow, .green 这四个 div 同在一个布局环境中,即便通过 .w_1, .w_2 这两个 div 划分,浮动之后它们还会一个接一个的排列,并不会因为有 div 划分而换行。而给 .w_1, .w_2 两个 div 创建 Block Formatting Context 后,这四个 div 便两两划分到不同的布局环境之中,从而闭合浮动。
3.阻止空白边折叠
.box{ width:300px; margin-bottom:20px; border:1px solid #ccc; } .div1{ background:#ccc; } .div2{ margin:30px 0; width:150px; }
<div class="box"> <div class="div1"> <div class="div2">我没有开启bfc</div> </div> </div>
div1的宽高都没有设置,它的宽度等于 box 的大小,高度等于 div2 的大小,当创建 Block Formatting Context 后,div1 和 div2 不再发生空白边折叠,深灰色的 div1 撑满了 box。
4.包含块计算高度时加上浮动元素
.box{ width:300px; border:3px solid #000; } .div1, .div2, .div3{ width:300px; height:30px; } .div1{ background:#ccc; } .div2{ background:#aaa; } .div3{ float:left; background:#ddd; } .bfc{ overflow:hidden; zoom:1; }
<div class="box bfc"> <div class="div1"></div> <div class="div2"></div> <div class="div3">浮动元素</div> </div>
普通流中的块级元素在进行高度计算时,浮动子元素不参与计算,当创建 Block Formatting Context 后,包含块计算高度时会加上浮动元素的高度。
5.避免普通流中的块容器与浮动元素相互覆盖
.box{ margin-bottom:60px; } .div1{ float:left; width:80px; height:80px; background:#FFD700; filter:alpha(opacity=50); opacity: 0.5;} .div2{ width:300px; height:60px; background:#018202; } .bfc{ overflow:hidden; zoom:1; }
<div class="box"> <div class="div1">浮动元素</div> <div class="div2 bfc">Block Formatting ContextBlock </div> </div>
div1 是个浮动元素,有50%的透明度。div2 是个一般的块元素,当 div2 没有创建 Block Formatting Context 时,它会与浮动元素重叠,但创建 Block Formatting Context 后,便不会重叠了。
6.三栏布局
.div1, .div2{ width:250px; } .div1{ float:left; } .div2{ float:right; } .bfc{ overflow:hidden; zoom:1; }
<div class="div1">左浮动</div> <div class="div2">右浮动</div> <div class="div3 bfc"></div>
三栏布局,左右两栏浮动并且固定宽度,中间创建 Block Formatting Context 后自适应。
7.两栏布局
.div1, .div2{ padding:10px; } .div1{ float:left; width:200px; } .bfc{ overflow:hidden; zoom:1; }
<div class="div1">Sidebar</div> <div class="div2 bfc">main</div>
两栏布局,左边栏固定宽度,右边创建 Block Formatting Context 后自适应。