BFC 的全称是 Block Formating Context,译为“块级格式化上下文”,是 CSS 规范中的一个概念,规定了一套渲染规则,规定了内部的子元素如何布局,以及他们和其他元素的关系等。
除了 BFC 之外,规范中还有 IFC 的概念,也就是 Inline Formating Context,译为“内联格式化上下文”。
BFC 和 IFC 都是 CSS 2.1 中的规范,在 CSS3 中,还有 GFC、FFC 等。
本文的重点是对 BFC 的理解,理解了 BFC 之后,就对 CSS 中的很多东西有了原理化的认知,更加明白 CSS 中的一些难点特性,如浮动、定位等。
你要知道的
在学习 BFC 之前,你需要知道下面几个要点:
- BFC 规定了浏览器对于元素和子元素渲染方式
- BFC 是需要触发条件的
- 只有触发了 BFC 的元素才能应用 BFC 的规则
- BFC 元素和
display:block
的元素没有半毛钱关系
BFC 的一些特性
BFC 包含以下一些常用特性:
- BFC 容器会阻止外边距叠加
- BFC 容器会阻止其被浮动元素覆盖
- 计算 BFC 容器的高度时,会包含浮动元素
这三个特性可以算是 BFC 中最常用的几个特性了,可以帮助我们理解浮动、清浮动等知识。
触发 BFC
满足下列任意条件,就可以触发 BFC:
-
float
设置为none
以外的值(left
,right
) -
overflow
设置为visible
以外的值(hidden
,auto
,scroll
) -
position
设置为relative
以外的值(absolute
,fixed
) -
display
设置为inline-block
,table
,table-cell
或table-caption
需要注意的是,display:table 本身并不会创建BFC,但是它会产生匿名框(anonymous boxes),而匿名框中的display:table-cell可以创建新的BFC,换句话说,触发块级格式化上下文的是匿名框,而不是display:table。所以通过display:table和display:table-cell创建的BFC效果是不一样的。
上面的文字引用于那些年我们一起清除过的浮动。
应用
了解了 BFC 的常用特性以及触发条件后,我们可以使用 HTML+CSS 来对这些理论进行验证。下面依次验证这几个特性:
BFC 容器会阻止外边距叠加
外边距叠加是在元素在垂直方向上margin
值的叠加效应,我在这篇文章中也做了一些总结,您可以进行查看。
1.设置元素的 float
属性
HTML 代码:
<div>
<p></p>
<p></p>
</div>
CSS 代码:
div{
height: 20em;
border: .1em dashed #ccc;
}
p{
margin: 0;
width: 5em;
height: 5em;
background: red;
}
p:first-of-type{
margin-bottom:5em ;
}
p:last-of-type{
float: left;
background: blue;
margin-top: 5em;
}
效果如下:
2.设置元素的
overflow
属性HTML 代码:
<div>
<p></p>
</div>
<p></p>
CSS 代码:
div{
overflow: hidden;
}
p{
margin: 0;
width: 5em;
height: 5em;
margin-top: 5em;
background: red;
}
div > p{
margin-bottom:5em ;
margin-top: 0;
background: blue;
}
效果展示:
3.设置元素的 display
属性
HTML 代码:
<div>
<p></p>
</div>
<p></p>
CSS 代码:
div{
display: table-cell;
}
p{
margin: 0;
width: 5em;
height: 5em;
margin-top: 5em;
background: red;
}
div > p{
margin-bottom:5em ;
margin-top: 0;
background: blue;
}
效果预览:
4.设置元素的
position
属性使用绝对定位固定定位的元素脱离了标准文档流,并且有了层级的概念,因此其边距不会和其他元素的边距产生叠加效应(因为不在同一个层级),这个效果不好演示,这里就略过了~
BFC 容器会阻止其被浮动元素覆盖
我们知道浮动元素是一个 BFC 容器,其脱离了标准的文档流,其后面元素就好像这个元素不存在一样。浮动元素会一直想或者向右移动,直到其碰到了父级元素或者其他元素的边缘才停止。
先看一个简单的 Demo:
HTML 代码:
<div>
<p></p>
<p></p>
</div>
CSS 代码:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em
}
展示效果:
可见,由于第一个段落采用了浮动,便脱离了标准文档流,其后面的元素就好像这个浮动元素不存在一样,直接挨着父级元素排列,所以视觉效果上,后面的那一个段落被覆盖掉了。
由于BFC 容器会阻止其被浮动元素覆盖,因此我们只需要让后面的段落触发 BFC 就可以阻止浮动元素的覆盖啦。
1.设置元素的
float
属性CSS 代码:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
float: left;
}
运行效果:
2.设置元素的
overflow
属性CSS 代码:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
overflow: hidden;
}
运行效果:
3.设置元素的
display
属性CSS 代码:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
display: inline-block;
}
运行效果:
4.设置元素的
position
属性CSS 代码:
div{
width: 20em;
height: 5em;
border: 1px dashed #ccc;
}
p{
width: 5em;
height: 5em;
margin: 0;
}
div >p:first-of-type{
background: red;
float: left;
}
div >p:last-of-type{
background: blue;
width: 10em;
position: absolute;
}
运行效果:
这个最霸道,不仅阻止了浮动元素对其自身进行覆盖,反而还把浮动元素给覆盖了,666
计算 BFC 容器的高度时,会包含浮动元素
这也就是清除浮动的原理了,因为浮动会将元素的 inline-box 设置为0,而我们知道 containing-box 的高度本质上是由 inline-box 决定的(您可以参考这篇文章,里面进行了一些总结),所以如果一个元素中的元素都进行了浮动,那么这个完成元素的高度就塌陷了。为了解决这个问题,我们只需要“找回”外层元素的高度就可以了,运用到的就是 BFC 的这个特性:计算 BFC 容器的高度时,会包含浮动元素。
关于浮动这一块,里面又有很多概念,需要再用一片文章来写,这里就不再往下写了。后面会出一篇和浮动有关的文章,再进行说明。
总结
本文主要讲解了 BFC 的概念,BFC 是 CSS 2.1 中的一项规范,规定了其和子元素的一些呈现方式。BFC 需要一些触发条件,和浮动、定位、行内块等知识点关系紧密,需要我们去深入理解。
附:参考资料
那些年我们一起清除过的浮动
理解 BFC (Block Formatting Model)
CSS之BFC详解
深度理解现代浏览器中的BFC和IE下的haslayout
完。