使用简单的 Sass Mixin 实现 CSS Grid 布局的浏览器兼容性

Avatar of Farley Reynolds
Farley Reynolds 发表于

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

根据 A List Apart 关于 CSS Grid 的一篇文章,一个“数字设计的新时代正在到来”。借助 FlexboxGrid,我们能够创建以前难以实现(甚至不可能实现)的布局。现在可以使用一个全新的系统来创建布局,尤其是在使用 Grid 时。但是,与大多数 Web 技术一样,浏览器支持始终是一个问题。让我们看看如何使 Grid 的基本方面在支持它的浏览器中都能正常工作,包括支持旧版且略有不同的 Grid 版本的旧版 Internet Explorer。

销售推介

如果您访问 caniuse.com,您会看到 CSS Grid 在所有主要浏览器的当前版本中都受支持,除了 Opera Mini。那么为什么不开始使用它呢?Rachel Andrew 广泛地论述了是否“安全使用”。是可以的,假设您没问题使用一个不能完全复制 Grid 功能的回退方案。

如果您的网站确实需要在所有浏览器中看起来都一样(无论这对您意味着什么),那么您将无法使用任何仅通过使用 Grid 才能使用的功能。在这种情况下,请不要使用 Grid 布局!如果您想要实现一些无法通过旧技术以良好方式实现的功能,请使用 Grid 布局。

如果您想开始学习 Grid,Jen Simmons 有 一个不错的链接集合,并且 这里有一个参考指南

Grid 是对 CSS 布局的一项重大更改。它功能强大、(相当)易于使用,并且如果您正在从事开源项目或团队合作,则开发人员也易于阅读。在本文中,我们将探讨如何编写 Grid 代码以使其尽可能兼容,包括一定程度的回退。

秘诀

本文的主要内容是解决 CSS Grid 基本功能的浏览器兼容性问题。我们将介绍如何构建父网格元素以及如何在其中放置子网格元素。

异常情况将是 Internet Explorer 和 Edge。Edge 刚刚开始发布现代 CSS Grid 语法,它是一个 Evergreen 浏览器,因此最终我们不必过多担心 Edge,但在撰写本文时,它确实很重要。IE 10 和 11 基本上处于停滞状态,并且都支持旧语法。

同样,Rachel Andrew 提供了有关此旧语法的资料,包括它支持什么以及如何使用它。例如,旧语法不支持 display: grid;,我们必须使用 display: -ms-grid;。许多属性也有类似的前缀。

即使这样,许多属性本身也不相同。但这没关系。差异并不大,我们可以从 Sass 获得一些帮助。这里的好处是,我们只需要为 IE/Edge 添加供应商前缀。其他任何浏览器都将由“标准”属性处理。

首先,让我们使用 Sass @mixin 定义一个网格父级。

@mixin display-grid {
  display: -ms-grid;
  display: grid;
}

.grid-parent {
  @include display-grid;
}

下面是一个演示,它还定义并布局了一个简单的网格。

查看 CodePen 上 Farley 编写的 CSS Grid 演示 1 (@farleykreynolds)。

这很有帮助,但网格本身尚不兼容旧版 CSS Grid 样式。

接下来,我们需要解决定义网格父级行和列的差异。让我们稍微增强一下网格,并将其定义为在所有浏览器中都兼容(例如,除了 grid-template-columns 之外,还使用 -ms-grid-columns)。

查看 CodePen 上 Farley 编写的 CSS Grid 演示 2 (@farleykreynolds)。

带有 -ms- 前缀的属性将适用于 IE/Edge,而没有前缀的属性将适用于其他支持网格的浏览器。此特定演示将为我们提供以下尺寸:

  • 一列宽 75px。
  • 一列占用其他列剩余的所有可用空间(1fr = 其他元素计算后剩余空间的 1 个分数)。
  • 两列,每列宽 50px。
  • 三行,每行高 1fr。

查看第 19 行的分组值。IE 和 Edge 没有用于分组所有尺寸相同的行或列集的语法。在任何其他浏览器中,我们可以使用 repeat() 函数实现相同的效果。

repeat([number of columns or rows], [width of columns or height of rows])

没有供应商前缀可以在这里帮助我们,我们需要使用旧语法手动写出每一列。

现在我们拥有了一个在所有浏览器中都兼容的网格,但我们仍然需要处理网格子元素。以下 CodePen 演示了如何使它们兼容。

查看 CodePen 上 Farley 编写的 CSS Grid 演示 2.5 (@farleykreynolds)。

这是在旧版和新版语法中放置网格项的 mixin。

@mixin grid-child ($col-start, $col-end, $row-start, $row-end) {
  -ms-grid-column: $col-start;
  -ms-grid-column-span: $col-end - $col-start;
  -ms-grid-row: $row-start;
  -ms-grid-row-span: $row-end - $row-start;
  grid-column: #{$col-start}/#{$col-end};
  grid-row: #{$row-start}/#{$row-end};
}

.child {
  @include grid-child(2, 3, 2, 3);
}

以下是您需要了解的不同浏览器中网格子元素属性之间的差异。在大多数浏览器中,您可以通过网格子元素开始和结束的网格线来定义它。网格线是您定义的列和行之间存在的线。语法如下所示:

grid-column-start: 3;
grid-column-end: 5;
/* or the shorthand version: */
grid-column: 3 / 5;

此元素将在您的网格中跨越第 3 到第 5 列线。

在 IE 和 Edge 中,您可以通过网格子元素开始所在的线以及它跨越的行或列数来定义它(没有像前面的示例那样简写版本)。语法如下所示:

-ms-grid-column: 3;
-ms-grid-column-span: 2;

此元素将从第 3 行开始,并跨越 2 列。以上两个代码段将有效地创建相同的元素。请注意,第一个代码段中的 5 – 3 等于 2,这与 IE/Edge 示例中的列跨度相同。这使我们能够在 @mixin 中进行一些快速计算,并从四个数字中获取所有必要的信息。第 17 行和第 19 行的减法设置了 IE/Edge 的跨度数字。

使用 @include grid-element; 允许您仅使用四个数字为任何浏览器定义网格子元素:列开始和结束,以及行开始和结束。

因此,现在我们有了适用于所有浏览器的网格父级和子级。

缺点和回退

不幸的是,并非所有浏览器都支持 CSS Grid,并且旧语法不支持现代语法中的所有内容。例如,grid-gapgrid-auto-rowsgrid-auto-columns 是现代语法中非常有用的属性,在旧语法中没有等效项。

有时您可以使用 @supports 来帮助您。@supports 的工作方式有点像媒体查询,如果它匹配,则应用其中的 CSS。

不过,这可能会变得非常棘手,因为 IE 不支持 @supports。当您想使用 grid-auto-rowsgrid-gap 等功能来自动化布局部分时,这就会产生一个难题,因为现在有三种情况:现代网格支持、使用 @supports 的旧网格支持、不使用 @supports 的旧网格支持。

@supports (display: -ms-grid) {
  /* This will apply in Edge (old syntax), but not IE 10 or 11 */
}

对于旧语法,您必须放置网格子元素并明确设置其边距,以便 IE 识别 CSS,这将使其他浏览器中自动放置或 grid-gap 变得没有必要。

由于 @supports 兼容性问题,以下 CodePen 有点像大杂烩。您可以看到 grid-auto-rows 的工作原理,以及如何在 IE/Edge 中设置间隙(grid-gap 在其中不起作用)。同样,如果您必须支持 IE,则明确设置值的需要可能会使自动设置布局样式的属性变得没有必要。

查看 CodePen 上 Farley 编写的 Grid 演示 3 (@farleykreynolds)。

grid-auto-rows 属性将根据列的填充情况自动生成指定高度的后续行。您可以通过在 CodePen 中添加更多 div 来使用它。每次您将 div 的数量增加到 3 的倍数(列数)以上时,都会添加一行。

grid-gap 属性基本上将网格子元素之间的线变成了沟槽。您可以使用所有常用的 CSS 尺寸单位(如 rem、em、像素等)来设置其值。在上面的演示中,涉及 nth-child 的属性设置了复制 IE 和 Edge 中 grid-gap 沟槽效果的边距。对于简单的网格来说,这并不难处理,但您可以看到,对于更高级或更灵活的网格,它可能会很快变得难以控制。

这两个属性和其他一些属性可以作为一些非常强大的布局的基础。如果您负责支持 IE 和 Edge,那么最终将取决于您是否认为您的项目值得为它们编写代码。网站在所有浏览器中不一定非得看起来相同,这也是事实。并且由于网格布局非常易于构建,因此可能值得多花一些时间。

我认为值得花一些时间考虑您的项目是否会从 CSS Grid 中获益,并在必要时使用@supports规则。

结论

CSS Grid 正在改变网页布局的构建方式和工作原理。浏览器支持可能始终是网络技术的难题,但这里的好处是 CSS Grid 的支持情况真的还不错。即使这样,差异也很容易在我们的代码中得到解决。CSS Grid 布局很棒且功能强大,并且借助 Sass 等工具的一点便利性帮助,它们也可以兼容。