在讲解BFC之前,先了解一下CSS中的三大常见布局定位方案:
普通流(normal flow):又叫文档流,在普通流中,元素的排列是按照在HTML中的先后位置自上而下的,行内元素水平排列,直到当行被占满然后换行,块级元素则会被渲染为完整的新的一行,除非另外指定,否则所有的元素都默认为普通流,也可以理解为,普通流中的元素位置由该元素在HTML文档中的位置决定。
浮动(float):在浮动布局中,元素先按照普通流的位置出现,然后根据浮动的方向,尽可能向左或者向右偏移。
绝对定位(absolute positioning):在绝对定位布局中,元素会整体脱离普通溜,因此绝对定位的元素不会影响到其兄弟元素, 元素的具体位置由绝对定位的坐标觉得。绝对定位的位置是相对于最近的已定位祖先元素,如果没有祖先元素,那么就相对最初的包含块。
在了解完上述定位方案后,讲一下BFC的概念:BFC(Box Formatting Context,格式化上下文)是W3C CSS2.1规范中的一个概念,是页面中独立渲染的一块区域,并且有相应的渲染规则,规定了其子元素如何定位,以及和其他元素的关系和相互作用。
BFC是上面提到定位方案中的普通流,具有BFC特性的元素可以看做是隔离了的独立容器,容器里面的元素不会影响到容器外面的元素,并且BFC元素具有一些特殊的性质。
如何触发BFC?只要元素符合以下的条件,就能够触发BFC:
(1)body根元素;
(2)浮动元素,float除了none以外的值;
(3)绝对定位元素:position(absolute,flex);
(4)display为inline-block,table-cells,flex;
(5)overflow除了visible以外的值,比如hidden,scroll,auto;
那么BFC元素具体有什么特性?
1.同一个BFC下外边距会发生折叠
<head>
div{
width: 100px;
height: 100px;
background: lightblue;
margin: 100px;
}
<head>
</body>
<div></div>
<div></div>
</body>
从效果上看,因为2个div都在同一个BFC容器下(body根标签),所以第一个div的下边距和第二div的上边距发生了重叠,2个div盒子的间隔只有100px,而不是200px。
首先这不是CSS中的bug,可以理解为一种规范,如果想避免外边距重叠,可以将2个盒子放到不同的BFC容器中。
2.BFC可以包含浮动的元素(清除浮动)
浮动的元素会脱离普通文档流,先看一下例子:
<div style="border: 1px solid #000;">
<div style="width: 100px;height; 100px;background: #eee;float: left;"></div>
</div>
可以看到,由于容器内元素浮动,脱离了文档流,所以容器只剩下了2px的边距高度,如果触发了BFC效果,容器就会包裹浮动元素
<div style="border: 1px solid #000;overflow: hidden;">
<div style="width: 100px;height: 100px;background: #eee;float: left"></div>
</div>
3.BFC可以阻止元素被浮动元素覆盖,先看一个文字环绕效果:
<div style="width: 100px;height: 100px;background: lightblue;float: left">我是一个左浮动元素</div>
<div style="widht: 200px;height: 200px;background:#eee">我是一个没有设置浮动,也没有触发BFC元素,widht: 200px;height: 200px;background:#eee</div>
这其实第二个元素有被浮动元素部分覆盖,但是文字信息不会被浮动元素所覆盖,如果想避免元素被覆盖,可以触发第二个元素的BFC特性,加入overflow: hidden;就会变成:
这个方法可以用来实现2列自适应的布局,这时候左边宽度固定,右边内容自适应宽度(将上面右边的内容的宽度去掉)