这是我参与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为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不为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: absolute、overflow: 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。
再比如下面这个问题
我们可以用 BFC 来解决
但同样的,我们也可以使用其他方法来替代 BFC,比如添加 border
总之,大多数时候都有可以替代 BFC 的方法,因此不必强行使用 BFC。
总结
- 没有必要非得去把 BFC 的定义解释清楚不可,能够以举例的方式说明 BFC 即可。
- BFC 可以用来处理一些常见的问题:例如清除浮动、margin 塌陷、左右自适应布局等。
- 大多数时候都有可以替代 BFC 的方法,因此不必强行去使用 BFC。