概述
BFC即Block Formatting Context。根据MDN上的定义,它是web页面上CSS可视化渲染的一部分,代表了一个渲染区域,块级元素在此区域中布局、浮动元素在此区域中与其它元素互相作用。
通俗理解它是页面布局规则中的一小套规则,是页面整体布局中的mini布局。BFC是一个容器,容器中按照一定的规则进行布局,不会影响容器之外的其它元素。BFC容器的产生具有一定的条件,BFC是CSS布局的基石。
一. 触发生成BFC的条件
• 根元素(,可以解释页面上正常流中block元素的行为了)
• 浮动元素(元素的 float 属性不是 none)
• 绝对定位元素(元素的 position属性 为 absolute 或 fixed)
• 行内块元素(元素的 display 属性为 inline-block)
• 表格单元格(元素的 display 属性为 table-cell,HTML表格单元格默认为该值)
• 表格标题(元素的 display属性 为 table-caption,HTML表格标题默认为该值)
• 匿名表格单元格元素(元素的 display 为 table、table-row、 table-row-group、table-header-group、table-footer-group(分别是HTML table、row、tbody、thead、tfoot 的默认属性)或 inline-table)
• overflow 计算值(Computed)不为 visible 的块元素
• display 值为 flow-root 的元素
• contain 值为 layout、content 或 paint 的元素
• 弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)
• 网格元素(display 为 grid 或 inline-grid 元素的直接子元素)
• 多列容器(元素的 column-count 或 column-width (en-US) 不为 auto,包括 column-count 为 1)
• column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)
二. BFC中的布局规则
- Box会在垂直方向,一个接一个地放置;
- Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生合并,如后文中的图4;
- 在BFC中,每一个盒子的左外边缘(margin-left)会触碰到容器的左边缘(border-left)(对于从右到左的格式来说,则触碰到右边缘);
- 对于浮动元素:BFC的区域不会与浮动盒子产生交集,而是紧贴浮动边缘;计算BFC的高度时,也会检测浮动或者定位的盒子高度。
三. 利用BFC可以做什么
1. 父容器包含浮动元素时高度发生塌陷
我是一个左浮动元素.
此处是文本,文本的数量多得足够包围浮动的图片的话,边框将可以框住整体
.outer {
border: 5px dotted rgb(214,129,137); border-radius: 5px;width: 450px;padding: 10px;margin-bottom: 40px;
}
.float {
padding: 10px;border: 5px solid rgba(214,129,137,.4);border-radius: 5px;background-color: rgba(233,78,119,.4); color: #fff;float: left; width: 200px;margin: 0 20px 0 0;
}
图1-文本够多,高度可包围浮动元素:
图2-文本少了,高度发生坍塌:
为什么会出现高度塌陷呢?
是因为当把元素设置为浮动之后,它就脱离了正常的文档流,此时由于容器outer没有设置高度,导致高度以其正常流中的文字高度为准。浮动元素与容器边框发生重叠。
有哪些解决办法呢?
1.利用CSS的hack:清除浮动;
2.利用本文中的BFC,把容器outer触发成为一个BFC,利用它可以包裹浮动元素的特性。
.outer {
border: 5px dotted rgb(214,129,137);border-radius: 5px;width: 450px;padding: 10px;margin-bottom: 40px;
/*解决方法 2:overflow: auto; 或者 display:flow-root;*/
}
/*解决方法 1:设置不可见的伪元素,清除浮动 */
.outer:after {
visibility: hidden;display: block;content: "";clear: both;height: 0;
}
图3:
2. 垂直方向上外边距合并
先看一段代码,体会下什么是外边距合并。可以看到,当为两个段落都设置为10px的上下外边距时,p1、p2之间实际只有一个10px,并非20px。另外,如果不将container生成BFC,则p1段落的上外边距也是不生效的,它会与div完全重叠,如图4。
我是container中的p1段落
我是container中的p2段落
.container {
background-color: #ccc;
}
p {
background-color: rgb(233,78,119);
margin: 10px 0;
}
图4:
对比图4中的两个差异,可以看到将container转变为BFC区域后,p1、p2的上下外边距生效。
为了理解同一个BFC中的外边距会发生合并,添加一个p3,并将它置于不同的BFC之中,从图5可以看到,此时,p3与p2之间即为正常的距离20px。由此也可以说明,BFC包含了它所含有的所有元素,但不包括创建了新BFC的子元素的内部元素。即人不可能同时踏入两条河流,BFC也一样,一个元素不可能同时属于两个BFC。
我是container中的p1段落
我是container中的p2段落
我是container中的p3段落
.container {
background-color: #ccc;
overflow: hidden;/* 将父容器设置为BFC */
}
p {
background-color: rgb(233,78,119);
margin: 10px 0;
}
.newBFC {
overflow: hidden; /* 创建一个新的BFC */
}
图5:
3. 自适应两栏布局的创建
前面的图1展示了文本包裹浮动元素的情况,如何设置文本不在包围浮动,从而实现一个两栏布局呢?利用BFC,很容易实现。
我是一个左浮动元素.
此处是文本,将我设置为一个BFC,我就不再包围浮动元素了,我自己玩自己的去咯~~~
.txt{
border: 5px solid rgba(214,0,0,.4);
border-radius: 5px;
overflow: hidden; /* 创建一个新的BFC */
}
图6:
四. BFC与文档流、布局的关系
通过上面的分析,可以看出BFC在页面布局特别是块级元素布局是十分重要的。那么BFC与文档流又是什么关系呢?文档流即normal flow,是页面中元素显示的规则,通过position属性和float属性,可以将元素从文档流脱离,形成定位流和浮动流。
normal流其实就是指FC(Formatting Context),直译过来是格式化上下文。FC它是页面中的一块CSS渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。常见的FC有BFC、IFC(Inline Formatting Contexts),还有GFC(GridLayout Formatting Contexts)和FFC(Flex Formatting Contexts)。
小结
本文首先概述了BFC的具体含义,并列出了如何可以形成BFC的方法,然后介绍了BFC区域的布局规则,并使用例子的方式重点介绍了利用BFC进行页面布局时可以解决的问题:浮动元素导致的高度塌陷、外边距合并问题以及自适应两栏布局的实现。最后还拓展介绍了BFC的兄弟、与页面布局中文档流的关系。CSS知识点比较杂散,抓住重点、逐一击破。加油~
参考文章:
understanding-css-layout-block-formatting-context
Block_formatting_context from MDN
BFC神奇背后的原理