阅读 226

什么是 BFC?

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

BFC 没有明确的定义

MDN 对 BFC 的描述

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。

下列方式会创建块格式化上下文

  • 根元素(<html>)
  • 浮动元素(元素的 float 不是 none
  • 绝对定位元素(元素的 position为 absolute 或 fixed
  • 行内块元素(元素的 display 为 inline-block
  • 表格单元格(元素的 display 为 table-cell,HTML表格单元格默认为该值)
  • 表格标题(元素的 display 为 table-caption,HTML表格标题默认为该值)
  • 匿名表格单元格元素(元素的 display 为 tabletable-row、 table-row-grouptable-header-grouptable-footer-group(分别是 HTML table、row、tbody、thead、tfoot 的默认属性)或 inline-table
  • overflow 计算值(Computed)不为 visible 的块元素
  • display 值为 flow-root 的元素
  • contain 值为 layoutcontent 或 paint 的元素
  • 弹性元素(display 为 flex 或 inline-flex 元素的直接子元素)
  • 网格元素(display为 grid 或 inline-grid 元素的直接子元素)
  • 多列容器(元素的 column-count 或 column-width 不为 auto,包括 column-count 为 1
  • column-span 为 all 的元素始终会创建一个新的BFC,即使该元素没有包裹在一个多列容器中(标准变更,Chrome bug)。

块格式化上下文包含创建它的元素内部的所有内容.

块格式化上下文对浮动定位与清除浮动都很重要。浮动定位和清除浮动时只会应用于同一个BFC内的元素。浮动不会影响其它BFC中元素的布局,而清除浮动只能清除同一BFC中在它前面的元素的浮动。外边距折叠也只会发生在属于同一BFC的块级元素之间。

CSS规范中对 BFC 的描述

浮动,绝对定位元素,非块盒的块容器(例如,inline-blocks,table-cells和table-captions)和'overflow'不为'visible'的块盒会为它们的内容建立一个新的块格式化上下文

在一个块格式化上下文中,盒在竖直方向一个接一个地放置,从包含块的顶部开始。两个兄弟盒之间的竖直距离由'margin'属性决定。同一个块格式化上下文中的相邻块级盒之间的竖直margin会合并

在一个块格式化上下文中,每个盒的left外边(left outer edge)挨着包含块的left边(对于从右向左的格式化,right边挨着)。即使存在浮动(尽管一个盒的行盒可能会因为浮动收缩),这也成立。除非该盒建立了一个新的块格式化上下文(这种情况下,该盒自身可能会因为浮动变窄)

张鑫旭对 BFC 的描述

BFC全称”Block Formatting Context”, 中文为“块级格式化上下文”。啪啦啪啦特性什么的,一言难尽,大家可以自行去查找,我这里不详述,免得乱了主次,总之,记住这么一句话:BFC元素特性表现原则就是,内部子元素再怎么翻江倒海,翻云覆雨都不会影响外部的元素。所以,避免margin穿透啊,清除浮动什么的也好理解了

从以上描述中,我们知道了:

  • BFC 的全称是Block Formatting Context,中文叫块格式化上下文
  • 如何去创建 BFC

至于 BFC 的定义什么的,诸如Web页面的可视CSS渲染的一部分块盒子的布局过程发生的区域浮动元素与其他元素交互的区域之类的概念,实在是有些抽象了(我是觉得对于初学者来说很难懂啦,大佬请无视我的发言)。

我们不难发现,MDN 和 CSS 规范中对 BFC 都只是对 BFC 进行功能性的描述,并没有给出非常明确的定义。

个人理解:BFC 并没有特别明确的定义,有的只是对 BFC 的特性/功能的描述。

BFC的功能

其实讲那么多 BFC 的定义我是觉得没多大用处的,还不如直接来看一下用 BFC 能够解决哪些问题来得实在

特性一:可以用 BFC 来包住浮动元素

类似于清除浮动

从上图中我们可以看出,BFC 区域不会与浮动重叠(触发 BFC 后,child 没有浮动在 parent 上方),即 BFC 内部是包含浮动元素的,会计算浮动元素的高度(触发 BFC 后,parent 被 child 撑开)

同理,我们可以将 MDN 中描述可以触发 BFC 的条件都试一下,如position: absoluteoverflow: hidden等都会产生上图中的效果,你可以自行试验。

但我们还是推荐使用 CSS3 新增的一个属性display: flow-root,因为该属性可以说是专门用来触发 BFC 的,而使用其他属性来触发 BFC 则可能会产生副作用,关于 BFC 的副作用见下文。

关于对display: flow-root这个属性的解释,可以参考一下 MDN

display: flow-root是一个新的 display 属性的值,它可以创建无副作用的 BFC。在父级块中使用 display: flow-root 可以创建新的 BFC。

其实,一个 BFC 不仅仅只是包住浮动元素,实际上

块格式化上下文包含创建它的元素内部的所有内容

也就是说,只要是在一个 BFC 内部,不管是浮动元素,还是绝度定位元素,或者元素的 margin、padding 等,全都应该是包含在这个 BFC 内部的。

特性二:两个 BFC 之间可以做到相互隔离

个人理解:每个 BFC 都是一个独立的容器,外部不会影响内部的元素,内部也不会影响外部的元素。即如果是两个 BFC 容器,它们会相互“隔离”,互不影响。

上图中,刚开始“哥哥”与“弟弟”重合在一起(“哥哥”是 BFC,“弟弟”不是),当为“弟弟”触发 BFC 后,“哥哥”与“弟弟”骤然分离。

利用 BFC 的这一特性,可以使用 float + div 来做 左右自适应布局

必须用 BFC 吗?

虽说使用 BFC 或许能解决 CSS 中的我们碰到的许多问题,但 BFC 却不是必需的,因为任何时候你能用 BFC 解决的问题,同样也可以用其他能够替代 BF C的方法来解决,而且使用 BFC 有时候还可能还会产生副作用。

举例说明:

比如上面的特性一的例子,虽说可以使用 BFC 来清除浮动,但如果你使用的是overflow: hidden这个属性来触发 BFC 的话,可能会产生一些非期待的副作用。

用 overflow:hidden 来触发 BFC 产生的副作用

可以使用上文中提到的display: flow-root来代替overflow: hidden

可以使用清除浮动(.clearfix)的方式来代替 BFC 的特性一,且无副作用。

又比如上面的特性二实现左右自适应布局,其实完全可以使用我们所熟悉的 flex 布局来代替 BFC。

flex 实现左右自适应布局

再比如下面这个问题

child的margin-top没有被parent包住

我们可以用 BFC 来解决

触发BFC后,parent被child的margin-top撑大

但同样的,我们也可以使用其他方法来替代 BFC,比如添加 border

总之,大多数时候都有可以替代 BFC 的方法,因此不必强行使用 BFC。

总结

  • 没有必要非得去把 BFC 的定义解释清楚不可,能够以举例的方式说明 BFC 即可。
  • BFC 可以用来处理一些常见的问题:例如清除浮动、margin 塌陷、左右自适应布局等。
  • 大多数时候都有可以替代 BFC 的方法,因此不必强行去使用 BFC。
文章分类
前端
文章标签