理解BFC(一)
写在前面
BFC(Block Formatting Context)块级格式上下文。熟悉CSS的应该知道,既然有块级,那是不是意味着其实也应该有内联级格式上下文呢?答案是肯定的。IFC(Inline Formatting Context)就是内联级格式上下文。
好了,既然知道有这两种格式上下文,那格式上下文到底是个什么东西?
什么是格式上下文(Formatting Context)
其实我觉得格式上下文这个翻译不太好。我们先来看看Formatting
的意思。
The way in which something is arranged or set out
翻译过来大概就是,东西排列的方式。所以,我觉得Formatting Context其实可以翻译为排版上下文。
所谓的上下文其实是一个环境。在这个环境中,所有的东西都按照一定的规则行动。就好像在一条河流里,如果放一堆木头,所有的木头必然都是从上游漂向下游。如果你放了一艘电动小船,它能从下游跑到上游,那么其实这艘电动小船就已经脱离了这个上下文了。
所以,格式上下文就是元素在这个环境下排列的方式。木头在河水中排列的方式和在湖中排列的方式肯定是有所不同的,因此块级格式上下文和内联格式上下文也是有所不同的。
块级和内联级格式上下文中分别有什么
换句话说,哪些元素是在块级格式上下文中,哪些元素是在内联格式上下文中呢?答案是显而易见的,甚至听起来像废话:
块级元素参与块级格式上下文,内联元素参与内联级元素上下文。并且一个元素只能参与一种格式上下文。
那么,元素在块级和内联级上下文中分别具体会发生什么呢?
块级格式上下文中元素的排列
“In a block formatting context, boxes are laid out one after the other, vertically, beginning at the top of a containing block. The vertical distance between two sibling boxes is determined by the ‘margin’ properties. Vertical margins between adjacent block-level boxes in a block formatting context collapse.” - 9.4.1
上面是CSS标准中对于块级格式上下文行为的描述。大致翻译一下就是:
在一个块级格式上下文中,元素从包含块的顶部开始,在垂直方向上一个接一个的排列。两个兄弟元素之间的垂直距离由margin决定。同一个块级格式上下文中,相邻的两个块级元素的margin会发生折叠(塌缩)。

注意⚠️,我们这里说的都是在水平的writing mode下。有些文字可能是垂直排布的,如古代汉语那样。如果垂直排布,只要把水平和垂直方向交换就可以,如下图所示,这里就不过多叙述了。

margin决定垂直距离
默认情况
默认情况下,块级元素有默认的margin:
One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.
Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”
p { |
<div class="box"> |
margin:0
将margin设置为0后,可以看到两个段落紧贴在一起:
One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.
Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”
p { |
<div class="box"> |
margin折叠(塌缩)
标准中规定了,同一个块级格式上下文中两个相邻的块级元素margin会发生折叠。也就是说,如果一个有bottom-margin的块级元素后面紧跟了一个有top-margin属性的块级元素,他们之间的距离不是两个margin的和,而是它们两者中较大的那个。
你可以打开开发者工具查看下面两个段落之间的margin不是20+40=60px,而是40px。
One November night in the year 1782, so the story runs, two brothers sat over their winter fire in the little French town of Annonay, watching the grey smoke-wreaths from the hearth curl up the wide chimney. Their names were Stephen and Joseph Montgolfier, they were papermakers by trade, and were noted as possessing thoughtful minds and a deep interest in all scientific knowledge and new discovery.
Before that night—a memorable night, as it was to prove—hundreds of millions of people had watched the rising smoke-wreaths of their fires without drawing any special inspiration from the fact.”
p { |
<div class="box"> |
内联级格式上下文中元素的排列
“In an inline formatting context, boxes are laid out horizontally, one after the other, beginning at the top of a containing block. Horizontal margins, borders, and padding are respected between these boxes. The boxes may be aligned vertically in different ways: their bottoms or tops may be aligned, or the baselines of text within them may be aligned. The rectangular area that contains the boxes that form a line is called a line box.” - 9.4.2
上面是CSS标准中对于内联级格式上下文行为的描述。大致翻译一下就是:
在内联级格式上下文中,元素从包含块的顶部开始,一个接一个的水平排列。这些元素水平方向上的margin、boder、padding会被计算(垂直方向上的不会)。这些元素有几种垂直对齐的方式:顶部对齐、底部对齐、基线对齐。包裹一行所有元素的矩形区域叫做行框
。
总结
一般来说,你可以把一个元素看作是有两个虚拟的框
,外面的框决定了它如何在相邻的元素中排布,里面的框决定了它的子节点如何排布。
例如对于inline-block,对外他是一个inline级别的元素,对内它则表现的像一个block级别的元素。你可以理解为对外它参与IFC,对内它参与BFC。
另外在CSS3中,还有Flex Formatting Context和Grid Formatting Context。这里就不展开了
这篇文章我们讲了BFC和IFC的表现形式,那么什么时候会产生独立的BFC呢?下篇文章我们就来讲讲这个。