IE 中的 CSS Grid:CSS Grid 和新的 Autoprefixer

Avatar of Daniel Tonon
Daniel Tonon on

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

本系列文章的第 1 部分,我揭穿了一些关于 Internet Explorer (IE) 实现 CSS Grid 的常见误解。本文在此基础上进行扩展。如果您还没有阅读过这篇文章,建议您先阅读这篇文章。

今天,我将解决最大的误解:在 IE 中使用 CSS Grid 实现非常困难。您现在就可以轻松地在 IE 中使用 CSS Grid,而无需提供任何糟糕的回退布局。其实并没有那么难。

文章系列

  1. 揭穿常见的 IE Grid 误解
  2. CSS Grid 和新的 Autoprefixer (本文)
  3. 使用间隙模拟自动放置网格
  4. 现在支持重复区域名称!

为 IE 提供糟糕的回退布局对客户来说有点难以接受。如果这是用于内联网,而 90% 的用户使用 IE,那么就更难了。如果您需要 IE 兼容性,首先需要接受您无法使用现代 CSS Grid 规范中所有花哨的功能。但不要灰心,您会惊讶于 IE11 可以处理多少内容,尤其是当它得到 Autoprefixer 的帮助时。

在深入讨论之前,您需要知道这不是一篇通用的“如何使用 CSS Grid”文章。本文适用于了解 CSS Grid,但由于 IE 的缘故,要么不敢使用,要么不允许使用它的人。

我将假设您已经很好地了解如何在现代浏览器中使用 CSS Grid。如果您不确定如何使用 CSS Grid,请观看 Rachel Andrew 出色的 CSS Grid 视频教程系列。之后,玩一些 Grid Garden 的浏览器游戏关卡,获得一些实践的 CSS Grid 体验。一旦您了解了如何在现代浏览器中使用 CSS Grid 的基本知识,就可以回到这里学习如何在 IE10 和 11 中使用它,以产生相同的结果。

设置 Autoprefixer

在做任何其他事情之前,您需要让 Autoprefixer 运行起来。Autoprefixer 是一种工具,用于自动将浏览器特定的 CSS 前缀添加到您的 CSS 中,这样您就不必手动添加。它有点像 Babel,但用于 CSS。(我们有一个由 Autoprefixer 创建者撰写的关于 Autoprefixer 的概述,可在 CSS Tricks 上找到。)

如果您以前从未使用过 Autoprefixer(或任何构建工具),那么首先在您的计算机上安装 Node,然后按照 本指南 的说明,设置一个基本的运行工作流。指南中专门介绍 Autoprefixer 的部分位于 此处。(如果您不确定使用哪种,我建议使用 Gulp 设置而不是 Grunt 设置。)

如果您已经在项目中使用 Autoprefixer,请确保使用此命令将其更新到最新版本

npm i autoprefixer@latest -D

Autoprefixer 最新版本中使用的一些功能在 PostCSS 5 版中不受支持。这意味着您可能还需要将 PostCSS 的版本更新到至少 6 版。如果您使用的是 Gulp,这意味着将 gulp-postcss 更新到至少 7.0.0 版。如果您使用的是 Grunt,您可能需要将 grunt-postcss 更新到至少 0.9.0 版。

一旦您拥有了运行的环境,您需要 **将 Autoprefixer 的 grid 设置设置为 true**。如果没有启用该设置,Autoprefixer 就无法执行我即将展示的任何酷炫功能。

**更新:** 在 9.3.1 版中,您可以通过简单地在 CSS 文件中添加控制注释来启用 CSS Grid 转换。在 第 4 部分 中了解更多信息。

启用网格设置的确切方法在很大程度上取决于您编译代码的方式。如果您使用的是 之前链接的指南,您会看到这段代码片段

var processorsArray = [
  // snipped for brevity
  require('autoprefixer')({ browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20']  })
];

WordPress 将代码片段中的所有“>”符号都转换为 >。似乎没有办法阻止它这样做。请假装代码片段中所有 > 实际上都是“>”符号。

grid: 'autoplace' 添加到选项中以启用网格前缀

var processorsArray = [
  // snipped for brevity
  require('autoprefixer')({ grid: 'autoplace', browsers: ['last 2 versions', 'ie 6-8', 'Firefox > 20']  })
];

**更新:** 在 9.4.0 版中,有限的自动放置支持 被引入到 Autoprefixer 中。出于向后兼容性的原因,现在启用网格转换的推荐设置是 grid: 'autoplace'。我已更新所有代码片段以反映此新建议。

顺便说一下,教程中的浏览器设置已经过时,会输出比实际需要的更多前缀。只需使用“>1%”,这意味着当浏览器不再使用时,Autoprefixer 会自动停止为该浏览器写入前缀。它根据从 caniuse.com 获取的全局浏览器数据来确定浏览器使用情况。

因此,您最终应该使用以下 Autoprefixer 设置

var processorsArray = [
  require('autoprefixer')({ grid: 'autoplace', browsers: ['> 1%'] })
];

现在让我们开始有趣的环节吧!😃

Autoprefixer 有了新的超能力!

您可能已经阅读了 Rachel Andrew 的文章 “我应该尝试使用 IE 实现的 CSS Grid 布局吗?” 那篇文章是关于 CSS Grid 的,并了解它在 IE10 和 11 中的支持情况。这是一篇很棒的文章,非常有助于理解 IE 的局限性。如果您还没有阅读过,一定要读一下。请注意,它在关于 Autoprefixer 的信息方面 **已经过时** 了。

自从 Rachel 撰写了她的 IE11 CSS Grid 文章以来,Autoprefixer 已经取得了长足的进步,现在 Autoprefixer 支持更多 CSS Grid 转换。请查看 Rachel 文章中基于 Autoprefixer 8.6.4 版的新更新版本表。请注意,**粗体** 中的项目表示与 Rachel 文章相比,Autoprefixer 支持发生了变化。

CSS Grid 属性 IE10 实现 Autoprefixer? 笔记
grid-template-columns -ms-grid-columns
grid-template-rows -ms-grid-rows
grid-template-areas NA Autoprefixer 使用它来了解网格的外观,但不添加任何额外的属性。
grid-template NA grid-template-columns、grid-template-rows 和 grid-template-areas 的简写
grid-auto-columns NA IE 不支持自动放置
grid-auto-rows NA IE 不支持自动放置
grid-auto-flow NA IE 不支持自动放置
grid NA 有关为什么不支持此功能,请参见 此 GitHub 问题
grid-row-start -ms-grid-row 1 跨度语法要求定义 grid-row-end
grid-column-start -ms-grid-column 1 跨度语法要求定义 grid-column-end
grid-row-end NA 1 必须定义 grid-row-start
grid-column-end NA 1 必须定义 grid-column-start
grid-row NA 1
grid-column NA 1
grid-area NA 2 Autoprefixer 将网格区域转换为列/行坐标
grid-row-gap NA 3 在 IE 中生成额外的行/列。
grid-column-gap NA 3 在 IE 中生成额外的行/列。
grid-gap NA 3 在 IE 中生成额外的行/列。
NA -ms-grid-column-span 从 grid-column-end 和 grid-area 转换而来。
NA -ms-grid-row-span 从 grid-row-end 和 grid-area 转换而来。
align-self -ms-grid-row-align
justify-self -ms-grid-column-align

表格免责声明

我将在本文后面更详细地介绍这些内容

  1. Autoprefixer 无法为负整数添加前缀。
  2. 每个网格元素必须具有唯一的区域名称。
  3. Autoprefixer 仅在定义了 grid-template-areasgrid-template-columns 两者 时才为 grid-gap 添加前缀。它也不能通过媒体查询继承 grid-gap

grid-template-areas 是你的新伙伴

正如你在更新后的(更积极的)表格中看到的,Autoprefixer 现在有很多很酷的新功能。其中最重要的就是它对 grid-template-areas(以及 grid-template)的支持。通过支持 grid-template-areas,Autoprefixer 现在能 完全 理解你的网格结构。这为 Autoprefixer 支持(有限的)grid-gap 铺平了道路。

请注意,Autoprefixer 仍然不支持 grid 属性的简写形式。这是一个刻意做出的设计决定,你可以在 这个 GitHub 问题 中了解更多信息。简而言之,grid 属性不仅是模板设置的简写,也是自动放置设置的简写。由于 IE 不能做自动放置,而 grid-template 属性基本上可以做到 grid 属性能做的一切(IE 可以处理的),因此决定不支持 grid 属性。

Rachel 在写她的文章的时候,为了支持 IE,你需要写这样的网格代码

/* IE-friendly source code 26 November 2016 */
/* Code needed to make Autoprefixer work properly */

.grid {
  display: grid;
  grid-template-columns: 1fr 10px 1fr;
  grid-template-rows: 100px 10px 100px;
}

.cell-A {
  grid-column: 1;
  grid-row: 1;
}

.cell-B {
  grid-column: 3;
  grid-row: 1;
}

.cell-C {
  grid-column: 1;
  grid-row: 3;
}

.cell-D {
  grid-column: 3;
  grid-row: 3;
}

现在,你可以这样写代码

/* Today’s IE-friendly source code */
/* Autoprefixer can now make this code IE safe */

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template:
    "a   b" 100px
    "c   d" 100px /
    1fr  1fr;
}

.cell-A {
  grid-area: a;
}

.cell-B {
  grid-area: b;
}

.cell-C {
  grid-area: c;
}

.cell-D {
  grid-area: d;
}

Autoprefixer 会将上面的代码转换为更适合 IE 的代码

/* Autoprefixer’s IE-friendly translation */

.grid {
 display: -ms-grid;
 display: grid;
 grid-gap: 10px;
 -ms-grid-rows: 100px 10px 100px;
 -ms-grid-columns: 1fr 10px 1fr;
 grid-template:
   "a   b" 100px
   "c   d" 100px /
   1fr  1fr;
}

.cell-A {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  grid-area: a;
}

.cell-B {
  -ms-grid-row: 1;
  -ms-grid-column: 3;
  grid-area: b;
}

.cell-C {
  -ms-grid-row: 3;
  -ms-grid-column: 1;
  grid-area: c;
}

.cell-D {
  -ms-grid-row: 3;
  -ms-grid-column: 3;
  grid-area: d;
}

最棒的是,你只需用媒体查询更改 grid-templategrid-template-areas 属性,Autoprefixer 就会自动为你更新所有网格单元格坐标

/* Changing a grid-template with a media-query */

.grid {
  display: grid;
  grid-gap: 10px;
  grid-template:
    "a   b" 100px
    "c   d" 100px
    "e   f" 100px /
    1fr  1fr;
}

@media (min-width: 600px){
  .grid {
    /* Duplicating the grid-gap is no longer necessary as of Autoprefixer v9.1.1 */
    grid-gap: 10px;
    grid-template:
      "a   b   c" 100px
      "d   e   f" 100px /
      1fr  1fr 1fr;
  }
}

.cell-A {
  grid-area: a;
}

.cell-B {
  grid-area: b;
}

.cell-C {
  grid-area: c;
}

.cell-D {
  grid-area: d;
}

.cell-E {
  grid-area: e;
}

.cell-F {
  grid-area: f;
}

上面会转换为以下 IE 友好代码

/* Autoprefixer’s IE-friendly media query translation */

.grid {
  display: -ms-grid;
  display: grid;
  grid-gap: 10px;
  -ms-grid-rows: 100px 10px 100px 10px 100px;
  -ms-grid-columns: 1fr 10px 1fr;
  grid-template:
    "a   b" 100px
    "c   d" 100px
    "e   f" 100px /
    1fr  1fr;
}

@media (min-width: 600px) {
  .grid {
    /* Duplicating the grid-gap is no longer necessary as of Autoprefixer v9.1.1 */
    grid-gap: 10px;
    -ms-grid-rows: 100px 10px 100px;
    -ms-grid-columns: 1fr 10px 1fr 10px 1fr;
    grid-template:
      "a   b   c" 100px
      "d   e   f" 100px /
      1fr  1fr 1fr;
  }
}

.cell-A {
  -ms-grid-row: 1;
  -ms-grid-column: 1;
  grid-area: a;
}

.cell-B {
  -ms-grid-row: 1;
  -ms-grid-column: 3;
  grid-area: b;
}

.cell-C {
  -ms-grid-row: 3;
  -ms-grid-column: 1;
  grid-area: c;
}

.cell-D {
  -ms-grid-row: 3;
  -ms-grid-column: 3;
  grid-area: d;
}

.cell-E {
  -ms-grid-row: 5;
  -ms-grid-column: 1;
  grid-area: e;
}

.cell-F {
  -ms-grid-row: 5;
  -ms-grid-column: 3;
  grid-area: f;
}

@media (min-width: 600px) {
  .cell-A {
    -ms-grid-row: 1;
    -ms-grid-column: 1;
  }
  
  .cell-B {
    -ms-grid-row: 1;
    -ms-grid-column: 3;
  }
  
  .cell-C {
    -ms-grid-row: 1;
    -ms-grid-column: 5;
  }
  
  .cell-D {
    -ms-grid-row: 3;
    -ms-grid-column: 1;
  }
  
  .cell-E {
    -ms-grid-row: 3;
    -ms-grid-column: 3;
  }
  
  .cell-F {
    -ms-grid-row: 3;
    -ms-grid-column: 5;
  }
}

重复的媒体查询可能看起来有点丑,但我向你保证,这是 Autoprefixer 处理媒体查询转换的最佳方式。新的 IE 网格单元格坐标无法放在与网格模板定义相同的媒体查询中。这样做会导致两种可能的结果之一。

一种结果是默认的网格单元格位置会覆盖媒体查询中声明的更改后的位置。这会导致媒体查询在 IE 中不起作用。

另一种结果是 Autoprefixer 会将媒体查询中的 所有 样式(是的,包括你自己编写的样式)移动到样式表中的另一个位置,这可能会导致可怕的 CSS 特定性问题。你可以在现在已关闭的 GitHub 问题 中了解更多关于这个决定的思考。

Autoprefixer 仍然不能解决所有问题

即使是超人也不能拯救所有人,Autoprefixer 也不例外。虽然 Autoprefixer 可以减少将我们的网格与 IE 兼容所需的工作量,但它不能解决所有问题。它只能转换 IE 可以理解的东西。如果你不希望某一天在 IE 中打开网站并导致网站崩溃,那么你需要了解以下几点。

Grid Gap 支持有限

你可能在最后一个例子中看到了,grid-gap 目前无法通过媒体查询继承。如果你想使用 grid-gap,你需要在定义网格模板的所有媒体查询中复制 grid-gap 设置。

更新: Autoprefixer 9.1.1 版本修复了 grid-gap 媒体查询继承错误。现在你可以安全地在默认网格模板中使用 grid-gap,然后让间隙设置传递到所有媒体查询网格模板中。

不过,使用 grid-gap 并不是唯一的麻烦。只有在同时定义了 grid-template-areasgrid-template-columns 时,Autoprefixer 才会支持它。

Autoprefixer 通过使用 grid-template-areas 来理解你的网格结构来添加 grid-gap 支持。然后它会获取你的 grid-template-columnsgrid-template-rows 定义,并在每行和列之间插入 grid-gap 值,在 IE 中创建额外的行和列。

如果你尝试在没有 grid-template-areas 的情况下单独使用 grid-gap,Autoprefixer 无法知道哪个单元格属于哪个网格。没有这个关键信息,它就不能安全地插入 IE 需要额外的列和行。

这解释了 grid-template-areas,但为什么我们还需要定义 grid-template-columns?像这样东西对 Autoprefixer 来说不应该很容易转换吗?

.grid {
  display: grid;
  grid-gap: 20px;
  grid-template-areas:
    "a  b  c"
    "d  e  f";
}

.cell-a {
  grid-area: a;
}

.cell-f {
  grid-area: f;
}

行和列在 CSS 网格中默认值为 auto,所以 Autoprefixer 无法添加类似 -ms-grid-columns: auto 20px auto 20px auto; 的东西吗?它对行做了,为什么不能对列做同样的事情呢?

好吧,我好奇的朋友,我在 第一部分 中解释过,auto 在 IE 中的行为与在现代浏览器中的 auto 有一些不同。当在 IE 中将列设置为 auto 时,它们总是会缩小到 max-content 的值。另一方面,现代网格列将在没有其他 fr 单位的情况下扩展到 1fr。这种差异会导致网格的现代版本和 IE 版本之间出现巨大的外观差异。Autoprefixer 团队认为对这一点做出假设太危险了,所以他们将 grid-template-columns 设置为 grid-gap 生效的强制设置。

所以这解释了为什么 Autoprefixer 在没有 grid-template-columns 的情况下不支持 grid-gap。如果 auto 在 IE 中表现得如此不同,那么为什么 Autoprefixer 在用户没有明确定义 grid-template-rows 的情况下支持 grid-gap 呢?难道那不是一样糟糕吗?

不完全是。当你对某个元素设置 display: grid; 时,它的宽度会增长到其容器的全部宽度。另一方面,它的高度通常会缩小到其内容的高度。当然,情况并非总是如此。有很多原因会导致网格高度超过其内容的高度。如果网格也是一个弹性项目,并且弹性容器比网格更高,那么这可能是导致网格高度超过其内容的一个原因。不过总的来说,如果没有其他力量参与,网格容器的高度总是与其内容的高度相同。

由于典型网格的高度与其内容的高度相同,在大多数情况下,IE 和现代浏览器中的 auto 行为将完全相同。只有当网格的高度超过其内容的高度时,它才会在功能上有所不同。为了在用户便利性和浏览器一致性之间取得最佳平衡,Autoprefixer 团队做出了选择。他们决定,支持缺少的 grid-template-rows 属性,但不支持缺少的 grid-template-columns 属性,是处理 grid-gap 支持的最佳方式。

没有自动放置!没有自动放置!没有自动放置!

更新: 尽管 IE 仍然不支持自动放置,但在 9.4.0 版本中,Autoprefixer 引入了有限的自动放置支持。阅读本节时,请记住它是在完全没有自动放置支持的情况下编写的。

我再强调一遍,在 IE 中使用 CSS 网格时,最重要的是要记住 所有 内容都必须 手动 放置。当你开始考虑使用自动放置时,你的网站就会在 IE 中崩溃。我有一种方法来处理具有未知单元格数量的网格。我会在本文的第三部分介绍。现在需要知道的是,如果你想以 IE 友好的方式使用 CSS 网格,你应该只在网格的行和列的单元格数量已知的情况下使用它。

正是 IE 中缺乏自动放置功能,使得能够通过 Autoprefixer 访问网格区域成为一种福音。你无需手动计算所有坐标,而是可以命名每个单元格,然后让 Autoprefixer 为你进行计算。当使用媒体查询时,你只需要重新定义网格模板,Autoprefixer 就会为你重新计算所有坐标。你很少需要进行列或行计数。太棒了!

区域名称必须唯一

更新: 本节内容现在已经过时。Autoprefixer 9.3.1 支持重复的区域名称。在本文的 第四部分 中了解更多信息。

使用 grid-template-areas 的能力是 Autoprefixer 最大的优势之一,尽管它也有局限性。Autoprefixer 无法访问 DOM。因此,Autoprefixer 完全依赖于使用区域名称来理解每个单元格需要放置在网格中的哪个位置。如果你在同一个样式表中两次使用相同的区域名称,这会导致冲突。

这里有一个小例子。在样式表开头,Grid Alpha 有 grid-template-areas: "delta echo"。在样式表后面,Grid Beta 有 grid-template-areas: "echo delta"。我们说我们的网格单元属于区域 echo……那么它是在第 1 列还是第 2 列呢?

.grid-alpha {
  grid-template-areas: "delta  echo";
}

.grid-beta {
  grid-template-areas: "echo  delta";
}

.grid-cell {
  /* What column does .grid-cell go in? */
  -ms-grid-column: ???;
  grid-area: echo;
}

现代浏览器确切地知道将网格单元放置在哪个列中,因为它们可以访问 DOM。如果单元格放置在 Grid Alpha 中,它将位于第一列。如果它被放置在 Grid Beta 中,它将位于第二列。Autoprefixer 只能读取你的 CSS。它不知道网格单元格是否被放置在 Grid Alpha 或 Grid Beta 中。它只知道网格单元格需要被放置在 "echo" 区域。Autoprefixer 通过选择样式表中最后出现的一个来解决这个难题。在本例中,Autoprefixer 将遵循 Grid Beta 的 "echo delta" 区域定义,因为它最后出现。如果你将网格单元格放在 Grid Alpha 中,它在现代浏览器中看起来很好,但在 IE 中将被放置在错误的列中。

这也意味着你不能真正使用为组件指定一个单个区域名称的策略,该名称被反复引用。在多个 grid-template-areas 属性中引用该区域名称,肯定会破坏 IE。你样式表中的每个网格中的每个区域名称都需要是唯一的,否则 Autoprefixer 会崩溃。

确保每个区域名称唯一的最简单方法是采用 BEM 风格的方法来命名区域。

.grid-alpha {
  grid-template-areas: "grid-alpha__delta  grid-alpha__echo";
}

.grid-beta {
  grid-template-areas: "grid-beta__echo  grid-beta__delta";
}

.grid-cell {
  /* No more conflict :) */
  -ms-grid-column: 2;
  grid-area: grid-alpha__echo;
}

如果有很多列和行,这可能非常冗长。你可能想要把它缩短为一个缩写。当然,你的区域名称越简短,发生冲突的可能性就越大。

.grid-alpha {
  grid-template-areas: "ga_delta  ga_echo";
}

.grid-beta {
  grid-template-areas: "gb_echo  gb_delta";
}

.grid-cell {
  -ms-grid-column: 2;
  arid-area: ga_echo;
}

有一个主要的例外。媒体查询中的网格区域可以是其他区域的副本,只要媒体查询中定义的区域名称针对的是同一个元素。如果没有这个例外,就无法根据屏幕尺寸更改网格区域。要记住的主要事情是,每个网格都必须有自己的一组唯一的区域名称,这些名称不能与任何其他网格共享。

@media (min-width: 600px) {
  .grid-one {
    grid-template-areas:
      "alpha bravo"
      "alpha charlie";
   }
}

@media (min-width: 900px) {
  .grid-one {
    /* This is fine */
    /* It is targeting the same element */
    grid-template-areas:
      "alpha bravo charlie";
  }
}

@media (min-width: 900px) {
  /* NOT FINE! */
  /* The "alpha" area is being reused on a different element! */
  .grid-two {
    grid-template-areas:
      "alpha delta";
  }
}

Autoprefixer 对跨列和跨行的支持有限

IE 实现的 CSS 网格中只有两个属性可以帮助你跨越多个列。主要的是 -ms-grid-column/row-span,它告诉 IE 跨越多少列/行。另一个是 -ms-grid-column/row,它告诉 IE 从哪里开始计数。

.grid-cell {
  -ms-grid-column-span: 2; /* number of cells to span */
  -ms-grid-column: 1; /* starting cell */
}

在现代浏览器中,你有更多选择。

Autoprefixer 友好

在现代跨越多个单元格的方法中,Autoprefixer 完全支持以下方法。请随意使用这些方法中的任何一个。

指定起始行和要跨越的行数(类似于 IE)

.grid-cell {
  grid-column: 1 / span 2;
}

指定结束行,然后向后跨越

.grid-cell {
  grid-column: span 2 / 3;
}

直接指定起始行和结束行

.grid-cell {
  grid-column: 1 / 3;
}

使用 grid-column/row-end 只指定要跨越的单元格数。记住 IE 无法自动放置。起始行仍然需要在样式表中的其他地方指定

.grid-cell {
  /* Make sure you specify a starting line elsewhere */
  grid-column-end: span 2;
}

只指定起始行

.grid-cell {
  /* The short way */
  grid-column: 1;

  /* The more verbose way */
  grid-column-start: 1;
}
Autoprefixer 不友好。这里有龙!

现在这是 Autoprefixer 达到其极限的地方。以下方法在现代浏览器中受支持,但不受 Autoprefixer 支持。这主要是因为 Autoprefixer 不知道网格单元格属于哪个网格,因为它只能根据样式表中的内容做出决定。

指定起始行以及要从显式网格末尾跨越的行数

.grid-cell {
  grid-column: 1 / -1;
}

从显式网格末尾指定起始行和结束行

.grid-cell {
  grid-column: -3 / -1;
}

只使用简写语法指定要跨越的行数 (GitHub 问题)

.grid-cell {
  /* Update: This is now supported as of Autoprefixer version 9.1.1 */
  grid-column: span 2;
}

只指定向后跨越(IE 无法向后跨越)

.grid-cell {
  grid-column-start: span 2;
}

只指定结束行(IE 不理解 end,Autoprefixer 不知道哪里是开始)

.grid-cell {
  grid-column-end: 3;
}

所以,基本上避免从网格末尾向后计数,你就会没事。😊

现在避免使用行名

现代网格的一个很酷的功能是为网格模板指定行名。而不是使用数字来引用行,你可以给行一个名称并引用它。由于 Autoprefixer 支持网格区域,你可能会认为它们也支持行名。不幸的是,情况并非如此。截至版本 8.6.4,Autoprefixer 不支持行名(在撰写本文时)。但别担心!它并非完全无法支持(至少不是完全无法支持),只是他们还没将其列为优先事项。如果你喜欢在网格中使用行名,请在 GitHub 的问题页面 上告诉他们。发布你的用例,这肯定会提高该功能的优先级。在此期间,看看你是否可以使用网格区域来代替它。

请记住,如果它将被实现,那么你的整个样式表中的每个行名都需要是唯一的。与网格区域一样,Autoprefixer 不知道哪个行名属于哪个网格。它唯一能判断的方法是你的样式表中的每个行名都是唯一的(不包括媒体查询)。

更新:由于现在支持重复的区域名称,因此没有理由不支持重复的行名。

你仍然需要测试!

只要你遵循我们目前为止涵盖的所有规则,IE 通常都会正常工作。也就是说,IE 仍然可能有点不可预测。最近,我将一个网格项目设置为垂直流动的弹性容器,并在 IE11 中遇到一个奇怪的错误。列宽设置为 minmax(min-content, 350px),但 IE 在这种情况下似乎将 min-content 视为 max-content。这完全破坏了布局。将其更改为 minmax(0, 350px) 修复了问题。这说明了 IE 的网格实现并不完美。

还有一些时候,你可能会意外地忘记显式地放置网格单元格。我们使用现代浏览器构建网格,因为它们拥有很好的网格开发工具(尤其是 Firefox)。现代浏览器拥有自动放置功能。这意味着你可能构建网格到一半,然后被叫去处理别的事情。当你回到办公桌时,你发现布局在浏览器中看起来很漂亮,但你完全忘记了你还没有显式地放置任何网格单元格。你继续进行下一步,全然不知你已经让 IE 处于完全崩溃的状态。

这两个问题都只有在你用 IE11 测试你的网站时才会暴露出来。每当你发现网格在现代浏览器中看起来不错时,请在 IE 中打开它,并仔细检查它是否仍然按照你的预期显示。

Autoprefixer 控制注释

尽管 Autoprefixer 尽了最大努力,但仍然有一些罕见的情况,Autoprefixer 似乎比帮助你更多地妨碍了你。如果你发现自己身处这样一种情况下,如果你不使用 Autoprefixer 翻译你的代码会更容易,那么你可以使用 "控制注释" 来关闭 Autoprefixer。

更新:从 Autoprefixer 9.3.1 开始,现在建议你使用新的网格控制注释来启用和禁用 CSS 网格翻译。在 第 4 部分 中了解更多关于这些控制注释的信息。

autoprefixer: off

此控制注释将关闭针对整个 CSS 块的 Autoprefixer 翻译。它不会对注释之前或之后的任何样式进行前缀处理。

/* Input CSS */

.normal-behavior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.off-behavior {
  display: grid;
  /* autoprefixer: off */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.normal-behavior-again {
  display: grid;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 1fr 1fr;
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.off-behavior {
  display: grid;
  /* autoprefixer: off */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.normal-behavior-again {
  display: -ms-grid;
  display: grid;
}

autoprefixer: ignore next

如果你需要更像一把手术刀而不是一把大锤,那么 /* autoprefixer: ignore next */ 控制注释更适合你。 "忽略下一个" 将跳过下一个 CSS 声明,而不是忽略整个 CSS 块。

/* Input CSS */

.normal-behavior {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.ignore-next-behavior {
  display: grid;
  /* autoprefixer: ignore next */
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
  -ms-grid-columns: 1fr 1fr;
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

.ignore-next-behavior {
  display: -ms-grid;
  display: grid;
  /* autoprefixer: ignore next */
  grid-template-columns: 1fr 1fr;
  -ms-grid-rows: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
}

预处理器注释

如果您在项目中使用 Sass(或其他 CSS 预处理器),请不要使用双斜杠(//)方法来编写这些注释。Sass 会在 Autoprefixer 有机会翻译代码之前,将这些注释删除。

/* Input SCSS */

.normal-behavior {
  display: grid;
}

.failed-off-behavior {
  // autoprefixer: off
  display: grid;
}

.successful-off-behavior {
  /* autoprefixer: off */
  display: grid;
}
/* Output CSS */

.normal-behavior {
  display: -ms-grid;
  display: grid;
}

.failed-off-behavior {
  display: -ms-grid;
  display: grid;
}

.successful-off-behavior {
  /* autoprefixer: off */
  display: grid;
}

让我们回顾一下!

所以,在经历了所有这一切之后,这里列出了成为 IE11 CSS 网格大师所需记住的所有事项

  • 使用最新版本的 Autoprefixer (npm i autoprefixer@latest -D)。
  • 打开 Autoprefixer 网格设置。
  • 不要尝试使用自动放置,每个单元格必须手动放置。
  • 使用 grid-template-areas 作为将网格单元格放置到位置的主要方法。
  • 使用 grid-template(而不是 grid)作为快捷方式。
  • 除非区域名称位于针对同一元素的媒体查询中,否则不要使用重复的区域名称。 (在 9.3.1 中不是问题)
  • 只要定义了 grid-template-areasgrid-template-columns,就可以使用 grid-gap
  • 跨越多个列和行时,避免从网格末尾倒着计数。Autoprefixer 对网格的理解还不够好,无法支持这一点。
  • 目前避免使用行名。如果您想开始使用它们,请给这个GitHub 问题 点赞。
  • 使用控制注释 /* autoprefixer: off *//* autoprefixer: ignore next */ 来阻止 Autoprefixer 翻译样式表中导致问题的某些部分。
  • 不要忘记测试!

…以及来自第 1 部分

  • IE 确实具有隐式网格。
  • IE 支持重复功能。
  • minmax()min-contentmax-content 都得到原生支持。
  • fit-content() 没有得到原生支持,但您可以使用 automax-width 设置来解决此问题。
  • IE 中的 auto 不等于现代浏览器中的 auto

如果您有任何问题,或者这确实对您有帮助,请在评论中告诉我!我还在 Twitter 上是 @Daniel_Tonon。😁

接下来…

在第 3 部分中,我将介绍如何在 IE11 中制作一个完全响应式的基于 flexbox 的网格。这种 flexbox 技术甚至复制了 grid-gap 功能!

文章系列

  1. 揭穿常见的 IE Grid 误解
  2. CSS Grid 和新的 Autoprefixer (本文)
  3. 使用间隙模拟自动放置网格
  4. 现在支持重复区域名称!