写在前面:啃了很久的BFC现在总算是有个交代了,文章里有很多一家之见,和目前能看到的大多数关于BFC的文章都有一些不一样的地方。也许我是错的,但是我真的认真思考过了。
一. 什么是BFC?
BFC的全称是Block Formatting Context,即块级格式化上下文。
格式化上下文是元素所处的一个自带一套布局规则的环境,这个环境决定了元素如何进行定位,如何与其他元素进行交互。
而BFC就是一个根据块布局规则布局子元素的格式化上下文,类似的概念还有内联格式化上下文(IFC)、灵活格式化上下文(FFC)、网格格式化上下文(GFC)。
BFC是一个独立的渲染区域,它的规则仅针对处于BFC内的子元素而言,即BFC类似一个结界,不会对自己环境之外的元素造成影响。
二. 怎么创建BFC?
- 根元素
- 浮动元素:元素的
float值不为none - 绝对定位元素:元素的
position值为absolute或fixed - 元素的
display值为inline-block、table-cell或table-caption - 元素的
overflow的值不为visible
注意,BFC指的是上述符合条件的元素创建出来的一个上下文,而不是元素本身。
三. BFC的特性和规则
-
BFC最重要的一个特性是:BFC能使其内部的元素和外部的元素相互隔离,内部元素无论如何作用都不会对外部产生影响。
-
根据MDN规范,BFC包括创建它的元素的内部的所有内容。
A BFC contains everything inside it, float and clear only apply to items inside the same formatting context, and margins only collapse between elements in the same formatting context.
BFC包括创建它的元素内部的所有内容,浮动和清除浮动只对处于同一格式化上下文的项目起效,且外边距塌陷的情况只会出现在处于同一格式化上下文的元素中。
-
在BFC内,盒子会在垂直方向上一个接一个的排列。这很好理解,因为BFC就是根据块布局规则来布局子元素的。
-
处于同一BFC中的两个相邻块级盒子,在垂直方向上的
margin值会产生外边距塌陷的情况。 -
BFC中每一个盒子的左外边缘都会直接接触到创建BFC的元素盒子的左边缘(对于从右往左的格式化时则相反)。注意这里是子元素的左外边缘接触父元素的左边缘,对于子元素盒子,左外边缘是
margin层的边缘。
四. BFC的应用
1. 清除浮动
在标准流布局的情况下,父元素的高度即使没有声明,也会被子元素的高度撑开。而使用浮动布局时,由于浮动元素的脱标特性,会出现父元素高度塌陷的情况。
要清除浮动子元素对父元素以及父元素之后的元素造成的影响,可以利用父元素创建一个BFC。
因为BFC包括创建它的元素内部的所有内容,所以BFC外层盒子的高度也会包括浮动元素的高度。
如何创建BFC,参考第二部分的内容。常见手段是给父元素添加overflow: hidden。
2. 解决外边距塌陷问题
可以给任意一个盒子创建新的BFC,生成一个独立渲染区域后,盒子的margin值不会受外界影响,就不会外边距塌陷了。
五. 一些问题
网上很多文章都说BFC包含创建该上下文元素的所有子元素,但不包括创建了新BFC的子元素的内部元素,但是我在MDN文档里并没有找到这个规范,MDN规范里只阐明了A BFC contains everything inside it。
但确实存在这样一个问题:在一个BFC里创建了新的BFC,那么新BFC里的元素和原BFC里的元素还属于同一BFC吗?
首先我们要知道,BFC的设计初衷是为了计算元素的高度,且BFC作为一个独立渲染区域,其内部布局不受外部影响。
我对此的个人理解是:新BFC仍然属于原BFC的一部分,但是新BFC对于原BFC来说类似一个黑箱自治区,即“我知道你属于我,但是我并不关心你的内部在做些什么”。
这也就可以解释,为什么BFC的高度会包括浮动元素(新BFC)在内(很多文章认为这是BFC的规则之一,但是我觉得这是结果而不是原因),因为浮动元素仍是原BFC的一部分,计算高度时不能落下它,就像祖国的版图不能落下任何一个自治区一样。
也可以解释为什么外边距塌陷可以用创建新BFC来解决,不是因为它们不属于同一BFC,而是因为新BFC对于原BFC转变成了黑箱状态,原BFC不再关心新BFC的内部,而只关心新BFC的高度了。
\