译者的话
这是我找到讲解 格式化上下文 (Block Formatting Context, BFC)
最棒的文章之一(下文统称 BFC
),由于 BFC
困扰我良久,希望这篇翻译能让 BFC
不再困扰大家。
翻译是机翻 + 修改,会有删减,另外强烈推荐阅读原文。
原文地址:www.smashingmagazine.com/2017/12/und…
导读
你可能从没听过“块格式化上下文”,但是如果你曾经用CSS做过布局,你可能就知道它是什么。本文将会讲述如何创建块格式化上下文,以及为什么它在CSS布局中很重要,并向展示创建块格式化上下文的新方法。
有些概念一旦理解会确确实实增加你的CSS技能熟练度,而理解 BFC
以及知道如何创建 BFC
非常有用,可以帮助加深对CSS布局的理解。这篇文章会有丰富且常见的例子帮助你理解 BFC
,并解释为什么你需要 BFC
。
什么是BFC?
只要通过一个简单的浮动布局的例子就可以理解 BFC
的行为。在下面的示例中,有一个 div
,div
里包含一个 向左浮动的div
和 一些文本
。如果文本足够多,就会环绕浮动元素,然后环绕整个区域。
<div class="outer">
<div class="float">I am a floated element.</div>
I am text inside the outer box.
</div>
.outer {
border: 5px dotted rgb(214,129,137);
border-radius: 5px;
width: 450px;
padding: 10px;
margin-bottom: 40px;
}
.float {
padding: 10px;
border: 5px solid rgba(214,129,137,.4);
border-radius: 5px;
background-color: rgba(233,78,119,.4);
color: #fff;
float: left;
width: 200px;
margin: 0 20px 0 0;
}
- 文本环绕着浮动元素
如果删除一些文本内容,那么就没有足够的内容来包围浮动元素,而且由于浮动是脱离文档流的,所以边框高度会变矮,只有到包含到文本的高度。即高度坍塌。
- 如果没有足够的文本,外部元素的边框就不会考虑浮动元素所需的高度
这是因为当我们浮动一个元素时,文本所在的框的宽度保持不变,为了给浮动元素腾出空间而缩短的是文本的空间。
我们通常有两种方法来解决这个布局问题。一种方法是使用 clearfix hack
(即清除浮动),它的作用是在文本和图像下面插入一个元素,并将其设置为 clear: both;
。另一种方法是使用 overflow
属性,将其值改为 visible
以外的即可。
.outer {
overflow: auto;
}
- 使用
overflow: auto
令外部的div包含浮动元素
另外,可以在CODEPEN中查看效果:codepen.io/rachelandre…
overflow
以这种方式工作的原因是,使用 除visible初值以外
的任何值都会创建一个 BFC
,而 BFC
的特性之一就是它可以包裹浮动元素。
译者注:重点之一, BFC
可以包裹浮动元素。即让浮动元素 看起来没有脱离文档流一样
,占据着其宽高大小的位置。
BFC 其实是你的布局中的mini布局
可以把 BFC
想象成页面内的迷你布局。一旦一个元素创建了一个 BFC ,所有的东西都包含在它里面。
正如我们所看到的,包括浮动元素,它们不再从盒子的底部伸出。 BFC
也会有一些其他有用的行为。
BFC可以防止外边距塌陷
理解边距坍塌是另一个被低估的CSS技能。在下一个示例中,有一个背景颜色为灰色的div。
这个div包含两个段落。外部div元素的页边距离底部40像素;段落的上下边距边都是20像素。
.outer {
background-color: #ccc;
margin: 0 0 40px 0;
}
p {
padding: 0;
margin: 20px 0 20px 0;
background-color: rgb(233,78,119);
color: #fff;
}
由于p元素的页边距与外部div的页边距之间没有任何内容,这两个元素将折叠起来,因此段落最终与框的顶部和底部齐平。我们在段落的上面和下面没有看到灰色背景。
- 边距塌陷,所以我们看不到框的顶部和底部是灰色的
如果我们为外部div元素创建一个 BFC
,它就会包含段落和它们的边距,这样它们就不会折叠,我们可以看到边距后面容器的灰色背景。
.outer {
background-color: #ccc;
margin: 0 0 40px 0;
overflow: auto; /* 创建BFC,参考:https://developer.mozilla.org/zh-CN/docs/Web/Guide/CSS/Block_formatting_context */
}
- 对于BFC容器,外边距不会坍塌
在CODEPEN中查看代码:codepen.io/rachelandre…
(译者注:在理解BFC之前,我都是在外部元素里设置padding实现同样的效果!)
再次说明, BFC
的工作是把东西装在盒子里,并且防止它们从盒子里跑出来。
BFC
可以让内容不再包裹浮动元素。您还将熟悉 BFC
的这种行为,因为使用浮动的任何列类型布局都是这样工作的。
如果一个项创建了一个 BFC
,那么该项目将不会包裹任何浮动元素。在下面的例子中,有这样的标记:
<div class="outer">
<div class="float">I am a floated element.</div>
<div class="text">I am text</div>
</div>
带有 float类
的项会向左浮动,因此div中的文本在它环绕 float
之后。
- 文本包围浮动元素
我们可以通过将包裹文本的div设置为BFC来防止这种环绕行为。
.text {
overflow: auto;
}
- 包含
text
类的div现在是BFC
,因此文本不会换行
这实际上就是创建多个列浮动布局的方法。浮动项还为该项创建了一个BFC,因此,就算右边的列比左边的列高,各个列也不会相互环绕。
在CODEPEN中查看代码:codepen.io/rachelandre…
还有什么方法能创建BFC?
除了使用 overflow
创建 BFC
外,其他一些CSS属性还创建 BFC
。正如我们所看到的,浮动元素创建了 BFC
。你的浮动项将包含它里面的任何东西。
在元素中使用position: absolute
或者 position: fixed
使用 display: inline-block
、 display: table-cell
或 display: table- title
。表单元格和表标题是这些HTML元素的默认设置,因此,如果有一个 table
,每个单元格都将创建一个 BFC
。
使用 column-span: all
,用于跨多列布局的列。 Flex
和 Grid
的项还创建了类似于 BFC
的东西,只不过它们分别被描述为 Flex格式化上下文(Flex Formatting Context, FFC)
和 网格格式化上下文(Grid Formatting Context, GFC)
。这反映了每个项参与的布局类型。 块格式化上下文BFC
表示项正在参与块布局,而 Flex格式化上下文
表示项正在参与Flex布局。在实际中,结果是相同的,浮动也可以被包含并且元素的 margin
边界不会坍塌。
创建BFC的新方法
使用 overflow
或其他方法创建 BFC
有两个问题。首先,这些方法的副作用是基于它们真正的设计目的。 overflow
方法创建一个 BFC
并包含浮动元素,但是在某些情况下,你会发现你得到了一个不需要的滚动条,或者阴影被剪切了。这是因为设计 overflow
属性的目的是让您告诉浏览器在溢出的情况下应该做什么——导致滚动条或剪切内容。浏览器正在做你让它做的事情!
即使在没有任何不想要的副作用的情况下,使用 overflow
也可能会让其他开发人员感到困惑。为什么 overflow
设置为自动或滚动?最初的开发者的意图是什么?他们想要这个组件上的滚动条吗?
另一个非常有用的创建 BFC
的方法是令其是惰性的,除了创建那个小布局和在其中安全地发生事情的能力之外,不会导致其他行为。该方法不会引起任何意外的问题,并且允许清楚地说明开发人员的意图。CSS工作组认为这可能也非常方便,因此我们有了 display
属性的一个新值—— flow-root
。
如果您有一个支持 display: flow-root
(如最新的Firefox或Chrome)的浏览器,您可以在下面的代码页中看到所有这些。
CODEPEN代码页面:codepen.io/rachelandre…
display: flow-root
的浏览器支持情况
浏览器对这个属性的支持是有限的,但支持还在增加,如果你认为它会很方便,一定要去给它投票。但是,即使你现在不能在代码中使用方便的 flow-root
特性,你现在也了解了什么是 BFC
,以及当你使用 overflow
或其他方法来包裹浮动元素时可以清楚的知道你在做什么。
你已经了解了关于浏览器如何布局web页面的一些非常基本的知识。虽然它们本身看起来无关紧要,但正是这些小知识可以加快创建和调试CSS布局所需的时间。