BFC在开发非常重要,每个人对其理解都有不同。本文章主要讨论BFC的一些实际应用。
BFC 的英文全称是:block formatting
context(块级格式化文本)。BFC可以理解为一个独立的渲染块,或者说是CSS布局单位。
常见BFC的触发条件
常见BFC的触发条件有:
1 2 3 4
|
position: absolute/fixed; diplay: inline-block/table-cells/table-captions; overflow: hidden; float: left/right;
|
下面来简单的看一个例子。
由于<
span>标签默认是行级元素,所以不能给其设置宽高,如果添加属性diplay:block;
它就可以设置宽高了。
1 2 3 4 5 6
|
span{ position: absolute; width: 100px; height: 100px; background-color: #000; }
|
将这样一段CSS添加给<
span>标签,改变的宽高就会生效。但并没有给其添加display:block属性。同样的”float:
left/right;”和 “position:
absolute/fixed;”也都会使其生效。实际上在使用这些属性的过程中,相当于隐式的给<
span>标签添加了属性”display: inline-block”。
这一性质其实并不常用,因为即使你不知道这些,你也可以在<
span>标签中手动的添加一个”display: block”来改变其宽高。
margin塌陷问题
先看一下这段代码:
1 2 3 4 5 6 7 8 9 10 11 12
|
.wrapper{ width: 200px; height: 200px; background-color: #fcc } .content{ margin-top: 100px; width: 100px; height: 100px; background-color: #ffc; }
|
1 2 3 4
|
// HTML代码 <div class="wrapper"> <div class="content"></div> </div>
|
我们再看一下这段代码执行后的效果:
按正常的理解,这段代码执行后的效果不应该是这样,我们想要的是子容器在父容器内部产生margin-top,而不是父容器产生margin-top。这就是大家熟知的margin塌陷问题,解决这个问题的方法有很多,有一种bug解决方法,可以在”.wrapper”中加入”border:1px
solid #ccc;”。当然,正常的解决方式就是利用BFC。
将触发BFC的条件属性写入”.wrapper”中,在这里不在写出代码。就可以解决这个问题。解决之后的效果是这样的:
上面的例子中还有一个很好玩的地方:
1 2 3 4 5 6 7 8 9 10 11 12 13
|
.wrapper{ width: 200px; height: 200px; background-color: #fcc margin-top: 100px; } .content{ margin-top: 100px; width: 100px; height: 100px; background-color: #ffc; }
|
1 2 3 4
|
// HTML代码 <div class="wrapper"> <div class="content"></div> </div>
|
这段代码执行的结果与上面的一样,为什么我们给父容器添加的margin-top没有生效?其实这里不仅仅是发生了margin塌陷现象,实际上还发生了margin的重叠现象。子容器的margin-top与父容器的margin-top重叠了。解决办法同上,还是给父容器添加BFC。添加完BFC就会出现我们想要的效果。
margin重叠
上面例子里有说到margin重叠,下面还有几种margin重叠的问题。看一下下面的例子。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
.content1{ height: 100px; width: 100px; background-color: red; margin-bottom: 100px; } .content2{ height: 100px; width: 100px; background-color: green; margin-top: 100px; }
|
1 2 3
|
// HTML代码 <div class="content1"></div> <div class="content2"></div>
|
这段代码运行的结果为:
看出问题了么,这两个margin发生了重叠,中间只有 100px
的距离。实际上,在这里的margin会取两个margin中大的数值作为实际显示出的数值。解决这个问题同样使用BFC。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
|
.content1{ height: 100px; width: 100px; background-color: red; margin-bottom: 100px; } .content2{ height: 100px; width: 100px; background-color: green; margin-top: 100px; } .wrapper{ overflow: hidden; }
|
1 2 3 4 5
|
// HTML代码 <div class="content1"></div> <div class="wrapper"> <div class="content2"></div> </div>
|
给任意一个content添加一个含有BFC的父容器,就可以解决这个问题。
同样的问题会发生在其它块级元素中,比如<
p>标签也会发生这种现象。
BFC可以看到BFC
叫这个标题感觉怪怪的,看一下下面的例子你就明白了。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
.content1{ height: 100px; width: 100px; background-color: red; float: left; } .content2{ height: 200px; width: 200px; background-color: green; }
|
1 2 3
|
// HTML代码 <div class="content1"></div> <div class="content2"></div>
|
这个例子显示的结果为:
这段代码第一个容器中添加了”float:
left;”属性,这样content1就会覆盖content2,如果我们不想让它覆盖,可以给第二个容器添加属性”float:left;”。实际上,我们也可以给第二个容器中添加BFC的触发条件,这样也同样能解决这个问题。这个过程,你可以这样理解,第一个容器添加了”float:left;”这个BFC触发条件,使第二个容器看不到它,所以会覆盖,如果想让第二个容器看到第一个容器,就为它添加一个BFC,因为BFC可以看到BFC。(注意:有一点要特殊说明,虽然BFC可以解决这个问题,但是其中不包括position,因为实际上position是个定位属性,在这个问题中,即使BFC看到了BFC,它也会按照position原本的定位去执行,如果觉得我说的抽象,可以自己敲代码试试。)
清除浮动
至于清除浮动的原理和为什么要清除浮动在这里不细说,过两天可能会单独写一章来说清除浮动。这里要说的是利用BFC可以清除浮动。
1 2 3 4 5 6 7 8 9 10
|
.content1{ height: 100px; width: 100px; background-color: red; float: left; } .wrapper{ border: 5px solid #000; }
|
1 2 3 4 5 6
|
// HTML代码 <div class="wrapper"> <div class="content"></div> <div class="content"></div> <div class="content"></div> </div>
|
这里给父容器设置了border,是为了更方便的看出父容器没有被撑开,所以需要清除浮动。用BFC清除浮动很简单,只需要在父容器中添加BFC触发条件就可以。比如:
1 2 3 4 5 6 7 8 9 10 11
|
.content1{ height: 100px; width: 100px; background-color: red; float: left; } .wrapper{ border: 5px solid #000; overflow: hidden; }
|
1 2 3 4 5 6
|
// HTML代码 <div class="wrapper"> <div class="content"></div> <div class="content"></div> <div class="content"></div> </div>
|
再来一个添加”float:left;”的效果图
注意:利用BFC清除浮动其实有很多问题
position:relative
在这里不会清除浮动,不细说。
position:absolute
将父容器的定位都改变了,在开发中这不是一个很好的做法。
float:
left
也是同理,虽然清除了子元素的浮动,却给父元素添加了浮动,如果不是特殊需要,这种方法也不是一个好的方法。
overflow:
hidden
有一个致命的问题,如果内容超出父容器或定位到父容器,就不会被看到,而且它不是按宽高撑开的。
display:
inline-block 在IE6 和IE7中没有这个属性值,所以行不通。
补充:
IE6 和 IE7
中清除浮动,我们需要触发其中的hasLayout为true,hasLayout为true就相当于BFC,那么怎么触发呢?只要将zoom设置为不为0的值。(zoom值为同比例缩放),下面是css
hack解决方式(开发中尽量避免css hack)。
1 2 3 4 5 6 7 8 9 10 11 12 13
|
.content1{ height: 100px; width: 100px; background-color: red; float: left; } .wrapper{ border: 5px solid #000; overflow: hidden; _zoom: 1; IE6 *zoom: 1; IE6/7 }
|
1 2 3 4 5 6
|
// HTML代码 <div class="wrapper"> <div class="content"></div> <div class="content"></div> <div class="content"></div> </div>
|
BFC的一些常见的简单应用就写到这里,可能后续还会有补充。关于BFC详细原理可以自己查一下,网上有很多介绍。有什么问题欢迎评论!