Autoprefixer 现在已经更新到 9.3.1 版本,自从我写了最初的三部分 IE 中的 CSS Grid 系列 以来,已经有了很多更新——其中最重要的更新是新的 grid-areas 系统。这主要归功于 Bogdan Dolin,他一直在努力解决大量的 Autoprefixer 问题。Autoprefixer 的网格转换之前就很强大,但现在它们变得更加强大!
文章系列
- 揭穿常见的 IE Grid 误解
- CSS Grid 和新的 Autoprefixer
- 用间隙模拟自动放置网格
- 现在支持重复区域名称!(本文)
Autoprefixer 如何支持重复区域名称
在 系列的第 2 部分 中,我指出了为什么 Autoprefixer 无法处理跨多个选择器使用的重复区域名称。
总而言之,这是我在文章中给出的示例
.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;
}
我们认为,由于 Autoprefixer 无法访问 DOM,因此无法知道网格单元格属于哪个网格,因此也无法知道网格单元格应该放在哪一列。
然而,我意识到了一些事情。网格单元格只受其直接父元素的影响(忽略 display: contents
)。这意味着如果网格单元格存在,它将始终是网格模板元素的直接子元素。这给了我一个关于如何解决网格区域名称冲突的想法!😁
.grid-alpha {
grid-template-areas: "delta echo";
}
.grid-beta {
/* Uh oh, duplicate area names! */
grid-template-areas: "echo delta";
}
.grid-cell {
/* We will use the first occurrence by default */
-ms-grid-column: 2;
grid-area: echo;
}
/*
We have detected a conflict!
Prefix the class with the parent selector.
*/
.grid-beta > .grid-cell {
/* NO MORE CONFLICT! */
-ms-grid-column: 1;
}
整个 grid-areas 系统需要重新编写才能实现这一点,但这绝对是值得的。
这个新系统的工作原理是,.grid-cell
将默认使用它遇到的第一个 grid-template-areas
属性。当它遇到冲突的网格模板时,它将创建一个新规则,将父选择器放在子选择器之前,如下所示
[full parent selector] > [direct child selector]
这就是我们仅通过查看 CSS 并了解 CSS Grid 工作原理就可以知道的
- 为了使 CSS Grid 工作,网格单元格必须是父网格容器的直接后代(假设不使用
display: contents
)。 grid-beta > .grid-cell
将仅对直接放置在.grid-beta
元素内的.grid-cell
元素起作用。.grid-beta > .grid-cell
对直接放置在.grid-alpha
元素内的.grid-cell
元素没有影响。.grid-beta > .grid-cell
对深度嵌套在.grid-beta
元素内的.grid-cell
元素没有影响。.grid-beta > .grid-cell
将覆盖单独的.grid-cell
CSS 规则的样式,这既是因为规则顺序,也是因为特异性。
由于这些原因,Autoprefixer 可以非常安全地解决这些冲突,而无需访问 DOM。
列表中的最后一点可能有点危险。它增加了特异性,这意味着它可能会导致某些 IE 样式以不同于现代覆盖样式工作的方式覆盖其他样式。由于生成的规则只包含 IE 特定的网格样式,并且它们只在非常特定的情况下应用,因此这不太可能在 99.999% 的情况下造成问题。但仍然存在边缘情况的可能性。
如果您发现需要增加网格单元格选择器的特异性,以下是如何操作。
不要写成这样
.grid {
grid-template-areas: "area-name";
}
.grid-cell {
grid-area: area-name;
}
…而是将规则写成这样
.grid {
grid-template-areas: "area-name";
}
.grid > .grid-cell {
grid-area: area-name;
}
Autoprefixer 将保留选择器并输出类似于以下内容的内容
.grid {
grid-template-areas: "area-name";
}
.grid > .grid-cell {
-ms-grid-column: 1;
-ms-grid-row: 1;
grid-area: area-name;
}
令人兴奋的新可能性!
那么为什么重复区域名称支持如此令人兴奋呢?
嗯,一方面,当在旧版本的 Autoprefixer 中意外使用重复区域名称时,它真的很烦人。它将在 IE 中中断,并且在旧版本的 Autoprefixer 中,它将静默失败。
然而,它令人兴奋的主要原因是它开辟了 IE 友好 CSS Grid 的全新世界!
使用修饰符类调整网格模板
这正是让我想要将重复区域名称支持添加到 Autoprefixer 的用例。想想这个。您有一个典型的网站,包含标题、页脚、主区域以及两侧的侧边栏。
查看 Pen 基本网站布局,作者是 Daniel Tonon (@daniel-tonon),发布于 CodePen。
有时我们想要两个侧边栏,有时我们想要一个侧边栏,有时我们不想任何侧边栏。当 Autoprefixer 不支持重复区域名称时,这很难管理,因为我们无法在多个网格模板之间共享区域名称。我们将不得不做类似的事情才能使它工作
/*
Before Duplicate area names were supported
- n = no side-bars
- f = first sidebar only
- s = second sidebar only
- fs = first and second sidebars
*/
.main-area {
display: grid;
grid-template:
"content-n" /
1fr;
}
.main-area.has-first-sidebar {
grid-template:
"first-sb-f content-f" /
300px 1fr;
}
.main-area.has-second-sidebar {
grid-template:
"content-s second-sb-s" /
1fr 300px;
}
.main-area.has-first-sidebar.has-second-sidebar {
grid-template:
"first-sb-fs content-fs second-sb-fs" /
200px 1fr 200px;
}
.main-area > .content {
grid-area: content-n; /* no side-bars */
}
.main-area > .sidebar.first {
grid-area: first-sb-f; /* first sidebar only */
}
.main-area > .sidebar.second {
grid-area: second-sb-s; /* second sidebar only */
}
.main-area.has-first-sidebar > .content {
grid-area: content-f; /* first sidebar only */
}
.main-area.has-second-sidebar > .content {
grid-area: content-s; /* second sidebar only */
}
.main-area.has-first-sidebar.has-second-sidebar > .content {
grid-area: content-fs; /* first and second sidebars */
}
.main-area.has-first-sidebar.has-second-sidebar > .sidebar.first {
grid-area: first-sb-fs; /* first and second sidebars */
}
.main-area.has-first-sidebar.has-second-sidebar > .sidebar.second {
grid-area: second-sb-fs; /* first and second sidebars */
}
Autoprefixer 转换
/*
Before Duplicate area names were supported
- n = no sidebars
- f = first sidebar only
- s = second sidebar only
- fs = first and second sidebars
*/
.main-area {
display: -ms-grid;
display: grid;
-ms-grid-rows: auto;
-ms-grid-columns: 1fr;
grid-template:
"content-n" /
1fr;
}
.main-area.has-first-sidebar {
-ms-grid-rows: auto;
-ms-grid-columns: 300px 1fr;
grid-template:
"first-sb-f content-f" /
300px 1fr;
}
.main-area.has-second-sidebar {
-ms-grid-rows: auto;
-ms-grid-columns: 1fr 300px;
grid-template:
"content-s second-sb-s" /
1fr 300px;
}
.main-area.has-first-sidebar.has-second-sidebar {
-ms-grid-rows: auto;
-ms-grid-columns: 200px 1fr 200px;
grid-template:
"first-sb-fs content-fs second-sb-fs" /
200px 1fr 200px;
}
.main-area > .content {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: content-n; /* no side-bars */
}
.main-area > .sidebar.first {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: first-sb-f; /* first sidebar only */
}
.main-area > .sidebar.second {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: second-sb-s; /* second sidebar only */
}
.main-area.has-first-sidebar > .content {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: content-f; /* first sidebar only */
}
.main-area.has-second-sidebar > .content {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: content-s; /* second sidebar only */
}
.main-area.has-first-sidebar.has-second-sidebar > .content {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: content-fs; /* first and second sidebars */
}
.main-area.has-first-sidebar.has-second-sidebar > .sidebar.first {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: first-sb-fs; /* first and second sidebars */
}
.main-area.has-first-sidebar.has-second-sidebar > .sidebar.second {
-ms-grid-row: 1;
-ms-grid-column: 3;
grid-area: second-sb-fs; /* first and second sidebars */
}
🤢 哦,对了,别忘了媒体查询!🤮
这个示例基于我必须为实际项目编写的实际代码……所以是的,我真的想要将重复区域名称支持添加到 Autoprefixer。
现在我们确实有了重复区域名称支持,我们可以将这段代码简化为更友好的内容 😊
/*
Duplicate area names now supported!
This code will work perfectly in IE with Autoprefixer 9.3.1
*/
.main-area {
display: grid;
grid-template:
"content" /
1fr;
}
.main-area.has-first-sidebar {
grid-template:
"first-sb content" /
300px 1fr;
}
.main-area.has-second-sidebar {
grid-template:
"content second-sb" /
1fr 300px;
}
.main-area.has-first-sidebar.has-second-sidebar {
grid-template:
"first-sb content second-sb" /
200px 1fr 200px;
}
.content {
grid-area: content;
}
.sidebar.first {
grid-area: first-sb;
}
.sidebar.second {
grid-area: second-sb;
}
Autoprefixer 转换
.main-area {
display: -ms-grid;
display: grid;
-ms-grid-rows: auto;
-ms-grid-columns: 1fr;
grid-template:
"content" /
1fr;
}
.main-area.has-first-sidebar {
-ms-grid-rows: auto;
-ms-grid-columns: 300px 1fr;
grid-template:
"first-sb content" /
300px 1fr;
}
.main-area.has-second-sidebar {
-ms-grid-rows: auto;
-ms-grid-columns: 1fr 300px;
grid-template:
"content second-sb" /
1fr 300px;
}
.main-area.has-first-sidebar.has-second-sidebar {
-ms-grid-rows: auto;
-ms-grid-columns: 200px 1fr 200px;
grid-template:
"first-sb content second-sb" /
200px 1fr 200px;
}
.content {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: content;
}
.main-area.has-first-sidebar > .content {
-ms-grid-row: 1;
-ms-grid-column: 2;
}
.main-area.has-second-sidebar > .content {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.main-area.has-first-sidebar.has-second-sidebar > .content {
-ms-grid-row: 1;
-ms-grid-column: 2;
}
.sidebar.first {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: first-sb;
}
.main-area.has-first-sidebar.has-second-sidebar > .sidebar.first {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.sidebar.second {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: second-sb;
}
.main-area.has-first-sidebar.has-second-sidebar > .sidebar.second {
-ms-grid-row: 1;
-ms-grid-column: 3;
}
有了这个 CSS,我们现在能够在网格元素上使用 has-first-sidebar
和 has-second-sidebar
类来修改浏览器使用的网格模板。我们不再需要担心定义网格单元格放置在哪个网格中。
分配组件可重复使用的区域名称
被迫使用唯一区域名称的局限性之一是,无法为组件提供单个一致的可重复使用的区域名称。我们被迫为每个网格想出唯一的区域名称。
现在 Autoprefixer 拥有了重复区域名称支持,这个限制消失了。我们可以为每个组件提供一个基于其组件名称的单个区域名称。然后,只要我们想将该组件放置在网格布局中,就可以引用该单个区域名称。
/* header.scss */
.header {
grid-area: header;
}
/* nav.scss */
.nav {
grid-area: nav;
}
/* sidebar.scss */
.sidebar {
grid-area: sidebar;
}
/* content.scss */
.content {
grid-area: content;
}
/* subscribe.scss */
.subscribe {
grid-area: subscribe;
}
/* footer.scss */
.footer {
grid-area: footer;
}
/* layout.scss */
.single-sidebar-layout {
display: grid;
grid-template-areas:
"header header"
"nav content"
"subscribe content"
"footer footer";
}
.double-sidebar-layout {
display: grid;
grid-template-areas:
"header header header"
"nav content sidebar"
"nav subscribe sidebar"
"footer footer footer";
}
Autoprefixer 转换
/* header.scss */
.header {
-ms-grid-row: 1;
-ms-grid-column: 1;
-ms-grid-column-span: 2;
grid-area: header;
}
.double-sidebar-layout > .header {
-ms-grid-row: 1;
-ms-grid-column: 1;
-ms-grid-column-span: 3;
}
/* nav.scss */
.nav {
-ms-grid-row: 2;
-ms-grid-column: 1;
grid-area: nav;
}
.double-sidebar-layout > .nav {
-ms-grid-row: 2;
-ms-grid-row-span: 2;
-ms-grid-column: 1;
}
/* sidebar.scss */
.sidebar {
-ms-grid-row: 2;
-ms-grid-row-span: 2;
-ms-grid-column: 3;
grid-area: sidebar;
}
/* content.scss */
.content {
-ms-grid-row: 2;
-ms-grid-row-span: 2;
-ms-grid-column: 2;
grid-area: content;
}
.double-sidebar-layout > .content {
-ms-grid-row: 2;
-ms-grid-column: 2;
}
/* subscribe.scss */
.subscribe {
-ms-grid-row: 3;
-ms-grid-column: 1;
grid-area: subscribe;
}
.double-sidebar-layout > .subscribe {
-ms-grid-row: 3;
-ms-grid-column: 2;
}
/* footer.scss */
.footer {
-ms-grid-row: 4;
-ms-grid-column: 1;
-ms-grid-column-span: 2;
grid-area: footer;
}
.double-sidebar-layout > .footer {
-ms-grid-row: 4;
-ms-grid-column: 1;
-ms-grid-column-span: 3;
}
/* layout.scss */
.single-sidebar-layout {
display: -ms-grid;
display: grid;
grid-template-areas:
"header header"
"nav content"
"subscribe content"
"footer footer";
}
.double-sidebar-layout {
display: -ms-grid;
display: grid;
grid-template-areas:
"header header header"
"nav content sidebar"
"nav subscribe sidebar"
"footer footer footer";
}
以下是我们得到的内容。请注意,这应该在 IE 中查看。
查看 Pen 组件区域名称技术,作者是 Daniel Tonon (@daniel-tonon),发布于 CodePen。
重复区域名称限制
目前 Autoprefixer 仍然无法处理一个相当常见的用例。当网格单元格的父选择器与网格模板选择器不匹配时,它会尝试解决重复区域名称
.grand-parent .mother {
grid-template-areas: "child";
}
.grand-parent .father {
grid-template-areas: "child child";
}
/* This will work */
.grand-parent .mother .child {
grid-area: child;
}
/*
This does not work because:
- ".uncle" != ".grand-parent .mother"
- ".uncle" != ".grand-parent .father"
- "child" is a duplicate area name
*/
.uncle .child {
grid-area: child;
}
以下是对 Autoprefixer 算法中当前限制的更现实的场景
.component .grid {
display: grid;
grid-template-areas: "one two";
grid-template-columns: 1fr 1fr;
}
/* This rule triggers duplicate area name conflicts. */
.component.modifier .grid {
grid-template-areas: "one ... two";
grid-template-columns: 1fr 1fr 1fr;
}
/*
This does not work because:
- ".component" != ".component .grid"
- ".component" != ".component.modifier .grid"
- area names "one" and "two" both have duplicate area name conflicts
*/
.component .cell-one {
grid-area: one;
}
.component .cell-two {
grid-area: two;
}
目前实际上只有三种方法可以解决这个冲突。
选项 1:从子元素中删除父选择器
在没有用于将样式范围限定到特定组件的任何安全措施的情况下,这是解决此问题的最危险的方法。我不推荐它。
.component .grid {
display: grid;
grid-template-areas: "one two";
grid-template-columns: 1fr 1fr;
}
.component.modifier .grid {
grid-template-areas: "one ... two";
grid-template-columns: 1fr 1fr 1fr;
}
.cell-one {
grid-area: one;
}
.cell-two {
grid-area: two;
}
Autoprefixer 转换
.component .grid {
display: -ms-grid;
display: grid;
grid-template-areas: "one two";
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
.component.modifier .grid {
grid-template-areas: "one ... two";
-ms-grid-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
.cell-one {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: one;
}
.component.modifier .grid > .cell-one {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.cell-two {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: two;
}
.component.modifier .grid > .cell-two {
-ms-grid-row: 1;
-ms-grid-column: 3;
}
选项 2:返回使用唯一区域名称
这个解决方案很丑陋,但如果你无法控制 HTML,那么这可能是处理问题最好的方式。
.component .grid {
display: grid;
grid-template-areas: "one two";
grid-template-columns: 1fr 1fr;
}
.component .cell-one {
grid-area: one;
}
.component .cell-two {
grid-area: two;
}
.component.modifier .grid {
grid-template-areas: "modifier_one ... modifier_two";
grid-template-columns: 1fr 1fr 1fr;
}
.component.modifier .cell-one {
grid-area: modifier_one;
}
.component.modifier .cell-two {
grid-area: modifier_two;
}
Autoprefixer 转换
.component .grid {
display: -ms-grid;
display: grid;
grid-template-areas: "one two";
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
.component .cell-one {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: one;
}
.component .cell-two {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: two;
}
.component.modifier .grid {
grid-template-areas: "modifier_one ... modifier_two";
-ms-grid-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
.component.modifier .cell-one {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: modifier_one;
}
.component.modifier .cell-two {
-ms-grid-row: 1;
-ms-grid-column: 3;
grid-area: modifier_two;
}
选项 3:使用 BEM 样式命名约定
是的,如果你使用 BEM 命名约定(或类似约定),这对你来说几乎永远不会是一个问题。如果这是一个选项,这无疑是处理该问题的首选方法。
.component__grid {
display: grid;
grid-template-areas: "one two";
grid-template-columns: 1fr 1fr;
}
.component__grid--modifier {
grid-template-areas: "one ... two";
grid-template-columns: 1fr 1fr 1fr;
}
.component__cell-one {
grid-area: one;
}
.component__cell-two {
grid-area: two;
}
Autoprefixer 转换
.component__grid {
display: -ms-grid;
display: grid;
grid-template-areas: "one two";
-ms-grid-columns: 1fr 1fr;
grid-template-columns: 1fr 1fr;
}
.component__grid--modifier {
grid-template-areas: "one ... two";
-ms-grid-columns: 1fr 1fr 1fr;
grid-template-columns: 1fr 1fr 1fr;
}
.component__cell-one {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: one;
}
.component__grid--modifier > .component__cell-one {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.component__cell-two {
-ms-grid-row: 1;
-ms-grid-column: 2;
grid-area: two;
}
.component__grid--modifier > .component__cell-two {
-ms-grid-row: 1;
-ms-grid-column: 3;
}
我对 BEM 有些问题,但通过对 语法进行一些调整,它可以成为一种非常好的方法来控制 CSS 特定性和范围。
其他 Autoprefixer 更新
在我写完关于 IE 的 CSS Grid 原文系列之后,Autoprefixer 已经进行了一些其他的更新。
不过,在深入探讨之前,以下是在 CodePen 中设置方法,以防您想自己尝试一下。
在 CodePen 中使用 Autoprefixer Grid 翻译
CodePen 已经升级到 Autoprefixer 的 9.3.1 版本。现在,您可以轻松地将 IE 友好的 CSS Grid 样式集成到您的项目中。首先,确保在 CodePen 设置中启用了 Autoprefixer(设置 > CSS > [供应商前缀] > Autoprefixer)。

然后,将全新的 /* autoprefixer grid: on */
控制注释添加到 CSS 面板的顶部。稍后我会详细介绍这个很棒的新功能。

更新:CodePen 现在也支持较新的 /* autoprefixer grid: autoplace */
控制注释。这意味着您现在可以使用 CodePen 来试验 Autoprefixers 的自动放置功能。😃
现在,您可以编写现代的 IE 友好的 CSS Grid 代码,CodePen 将自动为您添加所有 IE 前缀。


但是,为了在 IE 中实际测试您的项目,您需要在 “调试模式” 中查看该项目(更改视图 > 调试模式)。该项目需要保存才能访问此视图。

如果您想尝试一个可以显示实时 Autoprefixer 输出的工具,尝试一下专门为此设计的在线工具。在左侧输入 CSS 代码。它将在您键入时在右侧输出 Autoprefixer 翻译后的 CSS 代码。

新的 Autoprefixer 控制注释
我们并不总是能够更改 Autoprefixer 的配置设置。如果你之前曾经尝试在 CodePen 中进行一些 IE 友好的 CSS Grid 实验,你会知道无法直接访问 Autoprefixer 设置的痛苦。还有一些框架(如 Create React App 和 Angular)不允许用户更改 Autoprefixer 设置。还存在一定的技能门槛,阻止一些用户使用 Grid,因为他们不确定如何启用 Grid 翻译。
这个限制给许多用户带来了困扰,但后来 Andrey Alexandrov 提交了一个 pull request,引入了新的控制注释。这个新的控制注释使用户能够轻松地从CSS 文件中启用和禁用网格翻译。这比通过配置设置进行操作要容易得多。无论用户如何编译 CSS,它都对所有用户可用。
添加 /* autoprefixer grid: autoplace */
将为整个块启用网格翻译,而 /* autoprefixer grid: off */
将为该块禁用网格翻译。在一个块中,只有第一个网格控制注释将被应用。
/* Globally enable grid prefixes */
/* autoprefixer grid: autoplace */
.grid {
display: grid;
}
.non-ie .grid {
/* Turn off grid prefixes but only for this block */
/* autoprefixer grid: off */
display: grid;
/*
Grid control comments affect the whole block.
This control comment is ignored
*/
/* autoprefixer grid: autoplace */
grid-column: 1;
}
上面的代码将转换为以下代码(我已经过滤掉了解释注释)
/* autoprefixer grid: autoplace */
.grid {
display: -ms-grid;
display: grid;
}
.non-ie .grid {
/* autoprefixer grid: off */
display: grid;
/* autoprefixer grid: autoplace */
grid-column: 1;
}
@supports 可以禁用网格翻译
新的控制注释并不是选择性阻止 Autoprefixer 输出网格翻译代码的唯一方法。
Autoprefixer 将永远无法支持隐式网格自动放置。如果您使用 @supports
语句检查类似 grid-auto-rows: 0
的内容,Autoprefixer 不会为该语句中输入的代码输出 Grid 翻译。
.prefixed .grid {
display: -ms-grid;
display: grid;
}
/* Checking grid-auto-* support prevents prefixes */
@supports (grid-auto-rows: 0) {
.modern .grid {
display: grid;
}
}
/* Checking basic grid support still outputs prefixes */
@supports (display: grid) {
.still-prefixed .grid {
display: -ms-grid;
display: grid;
}
}
为了支持 IE,Autoprefixer 有时可能会生成大约 50 行额外的 CSS 代码。如果您在 @supports
语句中编写 Grid 代码,您需要关闭 IE 翻译,以减轻 CSS 的重量。如果您不想使用 @supports (grid-auto-rows: 0)
,那么可以在 @supports
语句中使用控制注释。
@supports (display: grid) {
.prefixed .grid {
display: -ms-grid;
display: grid;
}
}
@supports (display: grid) {
/* autoprefixer grid: off */
.modern .grid {
display: grid;
}
}
Autoprefixer 现在继承 grid-gaps
在原文系列中,我曾说过 Autoprefixer 无法继承 grid-gap
值。在 9.1.1 版本中,grid-gap
值能够通过媒体查询继承。在 9.3.1 版本中,它们也能够通过更具体的选择器继承。
.grid {
display: grid;
grid-gap: 20px; /* grid-gap is stated here */
grid-template:
"one two" /
1fr 1fr;
}
@media (max-width: 600px) {
.grid {
/* grid-gap is now inhereited here */
grid-template:
"one"
"two" /
1fr;
}
}
.grid.modifier {
/* grid-gap is now inhereited here as well */
grid-template:
"one"
"two" /
1fr;
}
.one { grid-area: one; }
.two { grid-area: two; }
Autoprefixer 转换
.grid {
display: -ms-grid;
display: grid;
grid-gap: 20px; /* grid-gap is stated here */
-ms-grid-rows: auto;
-ms-grid-columns: 1fr 20px 1fr;
grid-template:
"one two" /
1fr 1fr;
}
@media (max-width: 600px) {
.grid {
/* grid-gap is now inhereited here */
-ms-grid-rows: auto 20px auto;
-ms-grid-columns: 1fr;
grid-template:
"one"
"two" /
1fr;
}
}
.grid.modifier {
/* grid-gap is now inherited here as well */
-ms-grid-rows: auto 20px auto;
-ms-grid-columns: 1fr;
grid-template:
"one"
"two" /
1fr;
}
.one {
-ms-grid-row: 1;
-ms-grid-column: 1;
grid-area: one;
}
.grid.modifier > .one {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.two {
-ms-grid-row: 1;
-ms-grid-column: 3;
grid-area: two;
}
.grid.modifier > .two {
-ms-grid-row: 3;
-ms-grid-column: 1;
}
@media (max-width: 600px) {
.one {
-ms-grid-row: 1;
-ms-grid-column: 1;
}
.two {
-ms-grid-row: 3;
-ms-grid-column: 1;
}
}
grid-template: span X; 现在有效
在 本系列的第 2 部分 中,我曾提到以下语法无效
.grid-cell {
grid-column: span 2;
}
这个问题在 9.1.1 版本中已修复。它现在会转换为以下代码
.grid-cell {
-ms-grid-column-span: 2;
grid-column: span 2;
}
混合使用手动和区域放置的新警告
一位用户抱怨说 Autoprefixer 没有正确处理网格区域。经过进一步调查,我们意识到他们在同一个 CSS 规则中同时应用了 grid-area
和 grid-column
设置。
.grid {
display: grid;
grid-template-areas: "a b";
}
/* This doesn't work very well */
.grid-cell {
grid-column: 2;
grid-area: a;
}
要么单独使用 grid-area
,要么使用 grid-column
和 grid-row
。切勿同时使用两者。
如果您好奇,以下是 Autoprefixer 为上面的代码输出的内容
.grid {
display: -ms-grid;
display: grid;
grid-template-areas: "a b";
}
/* This doesn't work very well */
.grid-cell {
-ms-grid-row: 1;
-ms-grid-column: 1;
-ms-grid-column: 2;
grid-column: 2;
grid-area: a;
}
有一个例外。您可能需要一个网格单元格与其他网格单元格重叠。由于 Autoprefixer 使整体单元格放置变得多么容易,因此您需要使用 grid-template-areas
来放置网格单元格。但是,您不能真正使用 grid-template-areas
创建单元格重叠。要创建这种重叠,您可以在 grid-area
声明之后使用 grid-[column/row]-end: span X;
来强制重叠。
.grid {
display: grid;
grid-template-areas:
"a . ."
"a b b"
"a . .";
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
}
.grid-cell-a {
grid-area: a;
/* place cell span after the grid-area to force an overlap */
grid-column-end: span 2;
}
查看由 Daniel Tonon (@daniel-tonon) 在 CodePen 上创建的项目 column-span + grid-area 实验。
但是,如果您在网格中声明了网格间距,则需要手动编写列/行跨度前缀,同时要考虑 Autoprefixer 生成的额外列/行(IE 不支持 grid-gap
)。GitHub 上有 关于这个问题。
.grid {
display: grid;
grid-template-areas:
"a . ."
"a b c"
"a . .";
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: 1fr 1fr 1fr;
grid-gap: 10px;
}
.grid-cell-a {
grid-area: a;
/* IE column span added manually */
-ms-grid-column-span: 3; /* IE spans 2 columns + the gap */
grid-column-end: span 2; /* Modern browsers only span 2 columns */
}
查看由 Daniel Tonon (@daniel-tonon) 在 CodePen 上创建的项目 column-span + grid-area 实验 2。
该技术目前在 Autoprefixer 中会产生一条难以隐藏的警告消息。 此问题 已在 GitHub 上提出。
使用 [align/justify/place]-[content/items] 时出现新的警告
不幸的是,IE 无法从父容器对网格单元格进行对齐。在 IE 中对齐网格单元格的唯一方法是使用 -ms-grid-row-align
和 -ms-grid-column-align
属性。这些属性在现代网格语法中分别对应 align-self
和 justify-self
。
以下属性如果与 CSS 网格属性一起使用,将在 Autoprefixer 中触发警告
align-items
align-content
justify-items
justify-content
place-items
place-content
align-content
、justify-content
和 place-content
属性在 IE 中几乎不可能复制。另一方面,align-items
、justify-items
和 place-items
属性很容易通过使用子元素的 self
等效属性来复制(place-self
支持已在 9.3.0 中添加)。
/* [align/justify/place]-items is *NOT* IE friendly */
.align-justify-items {
display: grid;
align-items: start;
justify-items: end;
}
.place-items {
display: grid;
place-items: start end;
}
/*[align/justify/place]-self *IS* IE friendly */
.align-justify-grid { display: grid; }
.align-justify-grid > * {
align-self: start;
justify-self: end;
}
.place-grid { display: grid; }
.place-grid > * {
place-self: start end;
}
Autoprefixer 转换
/* [align/justify/place]-items is *NOT* IE friendly */
.align-justify-items {
display: -ms-grid;
display: grid;
align-items: start;
justify-items: end;
}
.place-items {
display: -ms-grid;
display: grid;
place-items: start end;
}
/*[align/justify/place]-self *IS* IE friendly */
.align-justify-grid { display: -ms-grid; display: grid; }
.align-justify-grid > * {
-ms-grid-row-align: start;
align-self: start;
-ms-grid-column-align: end;
justify-self: end;
}
.place-grid { display: -ms-grid; display: grid; }
.place-grid > * {
-ms-grid-row-align: start;
-ms-grid-column-align: end;
place-self: start end;
}
.grid { [align/justify/place]-items }
和 .grid > * { [align/justify/place]-self }
通常可以互换使用。这种替换并非总是有效,但在大多数情况下,这两种方法的行为非常相似。
下面是一个示例,展示了 IE 友好对齐方法和 IE 不友好对齐方法之间的区别。在现代浏览器中它们看起来相同,但在 IE 中,一个看起来与现代浏览器相同,而另一个则不同。
查看 CodePen 上 Daniel Tonon ( @daniel-tonon ) 编写的 place-items 实验。
就是这些了,朋友们
我希望你喜欢阅读有关 Autoprefixer 社区在过去几个月里为该项目做出的惊人改进。新的控制注释使得启用和禁用网格转换变得非常容易。新的网格区域系统也令人兴奋。我喜欢新的网格区域系统带来的所有 IE 友好 CSS 网格选项,我相信你也会喜欢。🙂
文章系列
- 揭穿常见的 IE Grid 误解
- CSS Grid 和新的 Autoprefixer
- 用间隙模拟自动放置网格
- 现在支持重复区域名称!(本文)