Flexbox 的向下支持

虽然弹性盒子被各种现代浏览器很好的支持,但是你或许还会遇到一些问题。在这个文档中,我们将会了解到浏览器支持弹性盒子的情况和一些潜在的问题,以及处理它们的资源和方法。

弹性盒子的历史

与所有 CSS 标准一样,弹性盒子标准经历了一系列的改动,直到它成为我们现有的候选推荐版本。作为候选推荐,我们不该着重于当下对于该规范的大量变动,尽管历来弹性盒子的迭代情况有所不同。

弹性盒子曾在许多浏览器中作为实验功能的方式被实现。当时进行实验性的实现的方式是使用浏览器前缀。这种关于前缀的构思是为了让规范的实现能被测试,并被浏览器工程师和网页开发者等在不和其他实现冲突的情况下浏览。也就是说不再生产代码中使用实验性的实现。然后,前缀最终被用在了生产代码中,结果对实验性规范的不管修改导致了人们需要不断对网站进行对应的修改。

在 2009 年时,规则看起来很不一样。当时,要创建一个弹性容器你会用display: box ,会有一大堆 box-* 属性,和现在的弹性盒子显然完全不同。

曾有一个规范的更新将语法换成了 display: flexbox ——这仍旧是浏览器前缀。

最后规范被修改成,定义 display: flex 作为创建弹性容器的方式。对于最新版本规范的浏览器支持自此就尽善尽美了。

有很多老的关于弹性盒子规范旧版本的文章还存着,但他们都容易通过弹性盒子容器创建的方式来辨别。如果你在其中找到任何关于display: box或者display: flexbox的内容,那么它们就是过时的信息。

浏览器支持情况

现代浏览器能够很好的支持 flexbox,并且大多数浏览器不需要前缀。2015 年,Safari9 是最后一个移除前缀的主流浏览器。2 个需要注意浏览器兼容的浏览器是:

  • Internet Explorer 10:使用 -ms- 前缀;
  • UC 浏览器:使用 -webkit- 前缀。

现在,IE11 已经支持 display: flex,但是在使用的时候会有一些 bug。

常见问题

由于经过了发展,flexbox 的大多数问题与规范的变更有关,而且事实上我们很多人都试图在生产中环境中使用实验性的规范。如果您要确保与旧版本的浏览器(尤其是 IE10 和 11)向后兼容,则 Flexbugs 网站是一个有用的资源。您将看到许多列出的 bug 都适用于旧的浏览器版本,并且在当前的浏览器中已修复。每个错误都有列出的解决方法 - 可以节省许多时间。

如果你想要支持非常旧的浏览器使用 flexbox 属性,在 CSS 中加入:

.wrapper {
  display: -webkit-box;
  display: -webkit-flex;
  display: -ms-flexbox;
  display: flex;
}

Autoprefixer Online是查看推荐使用前缀浏览器的有效方式,具体取决于您希望通过浏览器支持返回多少版本。您还可以从 Can I Use 中以获取浏览器支持的信息,以便在已经支持的浏览器中删除前缀

有用的向下支持技术

假设弹性盒子使用 display 的属性值定义,当我们需要为不支持弹性盒子的旧版本的浏览器提供支持时,向下支持(fallback)技术可以用来覆写布局方式。如果你使用其他布局方法作用于一个元素,随后该元素又成为了弹性盒子的 item,规范定义了会发生什么。

浮动元素

“浮动和清除浮动不会在 flex item 上触发浮动和清除行为,并且不会脱离当前文档流。” - 3. Flex Containers

在下面的示例中,我将两个块级元素浮动,然后给容器设置了 display: flex。这两个元素现在变成了弹性盒子元素,意味着它们会伸展使得高度相同,并且没有应用任何浮动行为。

你可以通过移除 display: flex 属性来测试这项向下支持行为。

display: inline-block

一旦一个 inline-block 元素成为了一个弹性盒子元素,那么它将被块级化,因此 display: inline-block 属性的诸如在元素间保留空白符等行为将不会被应用。

移除 display: flex 属性来查看该向下支持行为,你将会看见这两个元素之间多出的空白符,这是因为使用 display: inine-block 时会把空白符当成其他行内元素对待。

display: table-*

CSS 中表格相关的系列属性可能是非常有用的向下支持技术,因为它们允许一些设计模式,例如全高度列和垂直居中等,甚至可以向后兼容至 IE8。

假如你在 HTML 中对一个元素使用 display: table-cell,它将呈现为表格单元格样式。CSS 会创建一个匿名盒子来呈现这些元素,这样你就不用包裹每一个元素来呈现表格的行(row),以及另外一个元素来呈现这个表格自身。你无法看见或修改这些匿名盒子的样式,它们只是单纯的用来修补文档树。

如果你在父元素上设置了 display: flex,这些匿名盒子将不会被创建,这样你的元素就保留直接的子元素并成为了一个弹性盒子元素 — 失去所有表格元素的特性。

“注意:display 的某些属性值通常会在初始盒子周围触发匿名盒子的创建行为。如果该盒子是一个弹性盒子元素,那么它会先被块级化,使得匿名盒子不会被创建。例如,两个连续的弹性盒子元素设置了 display: table-cell 后,将会成为两个独立分开的 display: block 弹性盒子元素,而不是被包裹近单独的一个匿名表格中。” - 4. Flex Items

vertical-align 属性

下面的示例展示了 vertical-align 属性与 display: inline-block 结合使用的情况。display: table-celldisplay: inline-block 都允许使用该属性。使用 vertical-align 可以使垂直排列优先于弹性盒子。这个属性会被弹性盒子忽略,这样你就可以将它与 display: table-cell 或者 display: inline-block 结合使用来作为一个向下支持技巧,然后就可以在弹性盒子中安全地使用盒子排列属性。

特性枚举与弹性盒子

你可以使用特性枚举(feature queries)来检查弹性盒子的支持情况:

@supports (display: flex) {
  // 添加在支持的浏览器中书写的样式代码
}

注意 Internet Explorer 11 不支持特性枚举,但是支持弹性盒子。如果你觉得在 IE11 中实现不易并且希望对它使用向下支持布局,那么你可以使用特性枚举只在对弹性盒子支持良好的浏览器中使用弹性盒子属性规则。需要记住的是,如果你想用浏览器厂商前缀的弹性盒子属性来包含某版本的浏览器,你需要在特性枚举中包含该版本浏览器的前缀。下面的特性枚举例子就兼容了 UC 浏览器,它支持特性枚举并且支持旧版弹性盒子语法:

@supports (display: flex) or (display: -webkit-box) {
  // code for supporting browsers
}

查看更多关于特性枚举的信息请访问:Using Feature Queries in CSS

结尾

当我在这个指南中花时间来检查潜在的问题和向下支持技巧时,弹性盒子已经做好了在生产环境中运作的充分准备。该指南可能会在你遇到问题或者需要支持旧版本浏览器时帮到你。