【外文翻译】几分钟理解和使用BFC

1,869 阅读8分钟

译者的话

这是我找到讲解 格式化上下文 (Block Formatting Context, BFC) 最棒的文章之一(下文统称 BFC ),由于 BFC 困扰我良久,希望这篇翻译能让 BFC 不再困扰大家。

翻译是机翻 + 修改,会有删减,另外强烈推荐阅读原文。

原文地址:www.smashingmagazine.com/2017/12/und…

导读

你可能从没听过“块格式化上下文”,但是如果你曾经用CSS做过布局,你可能就知道它是什么。本文将会讲述如何创建块格式化上下文,以及为什么它在CSS布局中很重要,并向展示创建块格式化上下文的新方法。


有些概念一旦理解会确确实实增加你的CSS技能熟练度,而理解 BFC 以及知道如何创建 BFC 非常有用,可以帮助加深对CSS布局的理解。这篇文章会有丰富且常见的例子帮助你理解 BFC ,并解释为什么你需要 BFC

什么是BFC?

只要通过一个简单的浮动布局的例子就可以理解 BFC 的行为。在下面的示例中,有一个 divdiv 里包含一个 向左浮动的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包含浮动元素

使用overflow:auto属性

另外,可以在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容器,外边距不会坍塌

对于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,因此文本不会换行

包含文本的div现在是BFC,因此文本不会换行

这实际上就是创建多个列浮动布局的方法。浮动项还为该项创建了一个BFC,因此,就算右边的列比左边的列高,各个列也不会相互环绕。

在CODEPEN中查看代码:codepen.io/rachelandre…

还有什么方法能创建BFC?

除了使用 overflow 创建 BFC 外,其他一些CSS属性还创建 BFC 。正如我们所看到的,浮动元素创建了 BFC 。你的浮动项将包含它里面的任何东西。

在元素中使用position: absolute 或者 position: fixed

使用 display: inline-blockdisplay: table-celldisplay: table- title 。表单元格和表标题是这些HTML元素的默认设置,因此,如果有一个 table ,每个单元格都将创建一个 BFC

使用 column-span: all ,用于跨多列布局的列。 FlexGrid 的项还创建了类似于 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的浏览器支持情况

display: flow-root 的浏览器支持情况

浏览器对这个属性的支持是有限的,但支持还在增加,如果你认为它会很方便,一定要去给它投票。但是,即使你现在不能在代码中使用方便的 flow-root 特性,你现在也了解了什么是 BFC ,以及当你使用 overflow 或其他方法来包裹浮动元素时可以清楚的知道你在做什么。

你已经了解了关于浏览器如何布局web页面的一些非常基本的知识。虽然它们本身看起来无关紧要,但正是这些小知识可以加快创建和调试CSS布局所需的时间。