1 引言
BFC(Block Formatting Context),中文翻译为“块格式化上下文”。它有一个明显的特性,那就是如果一个元素拥有了 BFC 特性,那么它内部元素不受外部元素的影响,外部元素也不会受其内部元素的影响。
但到底什么才是 BFC 呢?
先来看看 MDN 对 的解释。
2 MDN 对 BFC 的解释
块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视化CSS渲染的一部分,是布局过程中生成块级盒子的区域,也是浮动元素与其他元素的交互限定区域。
下列方式会创建块格式化上下文:
- 根元素或包含根元素的元素
- 浮动元素(元素的 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 值不为 visible 的块元素
- display 值为 flow-root 的元素
- contain 值为 layout、content或 strict 的元素
- 弹性元素(display为 flex 或 inline-flex元素的直接子元素)
- 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
- 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1)
- column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。
创建了块格式化上下文的元素中的所有内容都会被包含到该BFC中。
块格式化上下文对浮动定位(参见 float)与清除浮动(参见 clear)都很重要。浮动定位和清除浮动时只会应用于同一个BFC内的元素。浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动。外边距折叠(Margin collapsing)也只会发生在属于同一BFC的块级元素之间。
感觉怎么样?反正我读下来的感觉就是:
好像也没具体的说什么是 BFC 。
3 BFC 的个人理解
个人感觉 BFC 就像女孩子的好感一样,没法说清楚什么才算是女孩子对你有好感,但是一旦女孩子对你有好感,你就知道了。
BFC 同理,没法说清楚什么是 BFC ,但是当 BFC 一出现,你就知道那个东西属不属于 BFC ,也就是拥有某些特定属性的东西就是 BFC ,能触发 BFC 的属性 MDN 上都有说明。
4 BFC 的用处
4.1 管住子元素
BFC 元素里面元素不能影响外面的元素,利用这个特性,可以用来管住子元素。
4.1.1 浮动元素
我们知道,当一个元素变成浮动元素后,那么它就会脱离文档流,对页面布局产生影响,利用 BFC 就可牢牢管住浮动元素,消除这种影响,
BFC 复制代码
从动态图中可以看到,当我们给child
元素加一个浮动时,它就会脱离father
元素的掌控,如果这时候把father
元素变成 BFC (float: left;
、 display: inline-block;
都可以将元素变成 BFC 元素,其他更多方法看 MDN 的解释),那么child
元素就会重新被father
元素所掌控。
对于清楚浮动,也可以利用clearfix
来实现,这个更推荐clearfix
,因为 BFC 有副作用,除了display: flow-root
之外,其他将元素变成 BFC 的都是给元素加了一个其他的属性,这就会造成副作用。
display: flow-root
是一个专门生成 BFC 的一个属性,但是它是一个高级属性,浏览器支持不全面。
4.1.2 margin
当我们给子元素一个margin
时,它的margin
部分会跑到父级元素外面去。
当给子元素加一个margin-top: 100px;
后,会发现子元素比父元素大了,这个时候把父级元素变成 BFC 后,父级元素又会重新把子元素包进来。
4.2 和兄弟划清界限
BFC 元素外面的元素不能影响其里面的元素,利用这个特性可以和兄弟元素划清界限,不受兄弟元素的影响。
4.2.1 清除外边距叠加
我们知道,在CSS当中,相邻的两个盒子(可能是兄弟关系也可能是祖先关系)的外边距可以结合成一个单独的外边距。这种合并外边距的方式被称为折叠,并且因而所结合成的外边距称为折叠外边距。
而当其中一个元素变成了 BFC 之后,里面的子元素就不会与这个元素的相邻元素发生外边距叠加。
来看例子。
BFC 复制代码
这时候会发生外边距叠加,它们中间的边距为20px
。如果存在 BFC ,就会与旁边的元素划清界限,也就不会发生外边距叠加了。
从代码及动态图可以看到,其实是father
元素里面的child
元素与father
元素的兄弟元素发生了外边距叠加,当father
元素变成 BFC 后,里面的child
元素与father
元素的兄弟消除了外边距叠加。
我们来看另外一种情况,看下面的动态图。
从图中可以看到,BFC 元素本身不会与其兄弟元素消除外边距叠加,它只能消除其子元素与 BFC 兄弟元素之间的外边距叠加。
4.2.2 打破兄弟浮动元素的压迫
我们知道当兄弟元素变成浮动元素后,它就会“骑”在我们身上,这我们肯定不能忍啊。那咋办呢?把我们自己变成 BFC 就好了。
BFC 复制代码
那我想离这个想压迫我的兄弟远点那怎么办?我们自然而然地想到了margin-left
,来试试margin-left: 20px;
,来看看效果。
咦?咋没用呢?来看看它的margin
。
原来兄弟元素虽然不能压迫我们自身,但它仍旧可以“骑”在我们的外边距上。正所谓 BFC 的一个特性:外部元素不能影响 BFC 内部元素,但没说外部元素不能影响 BFC 元素本身。
既然这样,那就加大力度,我来个margin-left: 120px
。
这下倒是与兄弟元素分开了,但有一个很大的缺点,当兄弟元素的宽度发生变化时,它们之间的间距也发生了变化,如果想要其间距固定怎么办?
我们换个思路,把margin
写在浮动元素上怎样?
从动态图中可以看到,当margin
写在浮动元素上后,不管其宽度怎么变,与兄弟 BFC 元素总会有着固定的间隔。
利用这个特性,我们能完成一个多栏的布局。
文章中如有错误之处,忘不吝赐教。
参考资料: