BFC 是 CSS 中一个比较重要的概念,也是面试经常考查的点…
什么是 BFC
BFC 全称是 Block Formatting Context,即块格式化上下文。
除了 BFC,还有:
- IFC(行级格式化上下文)- inline 内联
- GFC(网格布局格式化上下文)-
display: grid
- FFC(自适应格式化上下文)-
display: flex
或display: inline-flex
注意:同一个元素不能同时存在于两个 BFC 中
它是 Web 页面的可视 CSS 渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。怎么理解呢?实际就是说 BFC 是一个渲染区域,并且有自己的一套渲染规则,使其内部布局的元素具有一些特性。
BFC 提供一个独立的布局环境,BFC 内部的元素布局与外部互不影响。
块级元素
CSS 属性值 display 为 block,list-item,table 的元素。
块级盒具有以下特性:
- CSS 属性值 display 为 block,list-item,table 时,它就是块级元素
- 布局上,块级盒呈现为竖直排列的块
- 每个块级盒都会参与 BFC 的创建
- 每个块级元素都会至少生成一个块级盒,称为主块级盒;一些元素可能会生成额外的块级盒,比如
<li>
,用来存放项目符号
创建 BFC
以下元素会创建 BFC
- 根元素(
<html>
) - 浮动元素(
float
不为none
) - 绝对定位元素(
position
为absolute
或fixed
) - 表格的标题和单元格(
display
为table-caption
,table-cell
) - 匿名表格单元格元素(
display
为table
或inline-table
) - 行内块元素(
display
为inline-block
) overflow
的值不为visible
的元素- 弹性元素(
display
为flex
或inline-flex
的元素的直接子元素) - 网格元素(
display
为grid
或inline-grid
的元素的直接子元素)
以上是 CSS2.1 规范定义的 BFC 触发方式,在最新的 CSS3 规范中,弹性元素和网格元素会创建 F(Flex)FC 和 G(Grid)FC。
BFC 的特性
- BFC 是页面上的一个独立容器,容器里面的子元素不会影响外面的元素。
- BFC 内部的块级盒会在垂直方向上一个接一个排列
- 同一 BFC 下的相邻块级元素可能发生外边距折叠,创建新的 BFC 可以避免外边距折叠
- 每个元素的外边距盒(margin box)的左边与包含块边框盒(border box)的左边相接触(从右向左的格式的话,则相反),即使存在浮动
- 浮动盒的区域不会和 BFC 重叠
- 计算 BFC 的高度时,浮动元素也会参与计算
如果不太理解的,在下面 BFC 的应用我会提及。
BFC 的应用
自适应两列布局
左列浮动(定宽或不定宽都可以),给右列开启 BFC。
1 | /* html 代码 */ |
- 将左列设为左浮动,将自身高度塌陷,使得其它块级元素可以和它占据同一行的位置。
- 右列为 div 块级元素,利用其自身的流特性占满整行。
- 右列设置
overflow: hidden
,触发 BFC 特性,使其自身与左列的浮动元素隔离开,不占满整行。
这即是上面说的 BFC 的特性之一:浮动盒的区域不会和 BFC 重叠
防止外边距(margin)重叠
兄弟元素之间的外边距重叠
1 | /* html 代码 */ |
两个块级元素,红色 div 距离底部 10px,绿色 div 距离顶部 20px,按道理应该两个块级元素相距 30px 才对,但实际却是取距离较大的一个,即 20px。
块级元素的上外边距和下外边距有时会合并(或折叠)为一个外边距,其大小取其中的较大者,这种行为称为外边距折叠(重叠),注意这个是发生在属于同一 BFC 下的块级元素之间
根据 BFC 特性,创建一个新的 BFC 就不会发生 margin 折叠了。比如我们在他们两个 div 外层再包裹一层容器,加属性overflow: hidden
,触发 BFC,那么两个 div 就不属于同个 BFC 了。
1 | /* html 代码 */ |
这个关于兄弟元素外边距叠加的问题,除了触发 BFC 也有其他方案,比如你统一只用上边距或下边距,就不会有上面的问题。
父子元素的外边距重叠
这种情况存在父元素与其第一个或最后一个子元素之间(嵌套元素)。
如果在父元素与其第一个/最后一个子元素之间不存在边框、内边距、行内内容,也没有创建块格式化上下文、或者清除浮动将两者的外边距 分开,此时子元素的外边距会“溢出”到父元素的外面。
如下代码:
1 | /* HTML 代码 */ |
如上图,红色的 div 在绿色的 div 内部,且设置了margin-top
为 30px,但我们发现红色 div 的顶部与绿色 div 顶部重合,并没有距离顶部 30px,而是溢出到父元素的外面计算。即本来父元素距离顶部只有 20px,被子元素溢出影响,外边距重叠,取较大的值,则距离顶部 30px。
解决办法:
- 给父元素触发 BFC(如添加
overflow: hidden
) - 给父元素添加 border
- 给父元素添加 padding
这样就能实现我们期望的效果了:
清除浮动解决令父元素高度坍塌的问题
当容器内子元素设置浮动时,脱离了文档流,容器中总父元素高度只有边框部分高度
1 | /* html 代码 */ |
解决办法:给父元素触发 BFC,使其有 BFC 特性:计算 BFC 的高度时,浮动元素也会参与计算
1 | .parent { |
上面我们都是用的overflow: hidden
触发 BFC,因为确实常用嘛,但是触发 BFC 也不止是只有这一种方法,如上面写的所示。
比如可以设置float: left
; float: right
; display: inline-block
; overflow: auto
; display: flex
; display:" table
; position
为absolute
或fixed
等等,这些都可以触发,不过父元素宽度表现不一定相同,但父元素高度都被撑出来了。当然实际运用可不是随便挑一个走,还是根据场景选择。
- ps: 个人技术博文 Github 仓库,觉得不错的话欢迎 star,鼓励我继续写作吧~