为什么 CSS Grid 如此重要,我们为什么应该关注它?
好吧,CSS Grid 是第一个真正的网页布局系统。 它旨在将内容组织成列和行,并且最终为开发人员提供了几乎“神级”的控制屏幕的能力。 这意味着我们终于可以放弃几十年来用于设置网页元素的各种 hack 和变通方案——最终,这意味着复杂的布局和排版精美的页面现在不仅成为可能,而且简单且易于维护。
借助 CSS Grid,网络即将变得比我们习惯的更加美丽。
好的,但是 Grid 如何工作?网上有很多复杂的教程会深入很多细节,但我认为我们应该从最基础的部分开始。 我们在这里要制作的是一个相对简单的字体样本,其中包含页面上排列的一组字母表字符。
首先,我们将添加我们的标记
<div class='wrapper'>
<div class='letter'>
A
</div>
<div class='letter'>
B
</div>
</div>
首先,我们将为这些字母设置正确的font-size
和color
样式,然后我们将使用 flexbox 属性(如align-items
和justify-content
)将这些字母居中在 div 中。 没错!CSS Grid 并没有取代 flexbox 属性,而是补充了它们已有的功能。 我们甚至可以将许多这些属性与 CSS Grid 结合使用。 但现在让我们回到演示

在上面的示例中,我们有两个简单的 div 彼此叠加,因为它们的默认值为display: block
。 接下来,我们将设置父元素以使用 Grid 布局
.wrapper {
display: grid;
}
这将导致以下结果
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 1。
现在您可能会注意到实际上没有任何变化。 而且您是对的!与设置display: inline-block;
或display: inline;
不同,当我们将 display 设置为grid
时,结果并不完全清楚。 事实上,为了让我们的网格真正发挥作用,我们首先需要为其提供一定数量的列或行。 在此示例中,我们只需将字母彼此相邻排列成两列
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
grid-column-gap: 1px;
background-color: black;
}
让我们分解这些新的代码行。 首先,我们使用grid-template-columns
创建网格的两列。 如果您以前从未见过1fr
值,它可能会显得非常奇怪,但它是一个有效的 CSS 单位,它指示每一列占据网格的一个分数。 在这种情况下,这意味着将有两列宽度相等。
最终看起来会像这样
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 2。
万岁!它起作用了。 但是您看到两列之间那个奇怪的间隙了吗?那是wrapper
的背景透过每个letter
div 显示,这是因为我们将grid-column-gap
属性设置为 1px。 通常,我们会希望设置更大的column-gap
,尤其是在我们将文本块彼此对齐时。 但在此示例中,一个像素对我们来说足够了。
那么,如果我们在标记中添加两个新字母会发生什么?这将如何改变布局?
<div class='wrapper'>
<div class='letter'>
A
</div>
<div class='letter'>
B
</div>
<div class='letter'>
C
</div>
<div class='letter'>
D
</div>
</div>
好吧,从技术上讲,它根本不会改变网格——我们已经告诉网格有两列,因此这两个字母 div 将直接位于其他字母下方,并且宽度正好为1fr
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 3。
现在奇怪的是——为什么字母 A 和 C 之间以及 B 和 D 之间没有 1px 的间隙?好吧,grid-column-gap
仅适用于列,而我们在这里实际上做的是在网格中创建了一个新的行。 我们需要使用grid-row-gap
才能看到该更改生效
.wrapper {
grid-column-gap: 1px;
grid-row-gap: 1px;
/* other styles go here */
/* we could have also used the shorthand `grid-gap` */
}
以下是其外观
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 4。
我们创建了第一个网格。 我们创建了一行和一列,而我们真正需要做的只是更改标记。 但是让我们进一步探索一下我们的列。 如果我们在grid-template-columns
属性中添加另一个值会发生什么?像这样
.wrapper {
grid-template-columns: 1fr 1fr 1fr;
}
好吧,我们当然会创建另一列!并且请注意,我们现在可以清楚地看到包装器元素的背景,因为没有子元素来填充该空间
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 5。
如果我们更改该属性中fr
的值,则实际上会创建所谓的非对称网格。 假设我们希望网格中的第一列占用其他两列空间的三倍
.wrapper {
grid-template-columns: 3fr 1fr 1fr;
}
这将导致包含A和D的列比其他两列更大,正如我们预期的那样
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 6。
这难道不强大吗?我们不再需要担心负边距或网格列的完美%值才能正确对齐内容。 我们可以创建超级复杂的网格,而无需进行过去必须进行的任何数学运算。 现在,我们只需要在grid-template-columns
属性中添加一个新值,瞧,一个新的网格列就会像魔法一样出现!
但是,您可能会问,响应式网格呢?这实际上就像在媒体查询中更改该属性一样简单。 假设我们希望将 2 列作为默认网格大小,然后在 500px 时希望 3 列,最后,在更大屏幕上,我们将所有内容移到 4 列中。 我们只需要编写以下内容
.wrapper {
display: grid;
grid-template-columns: 1fr 1fr;
}
@media screen and (min-width: 500px) {
.wrapper {
grid-template-columns: 1fr 1fr 1fr;
}
}
@media screen and (min-width: 800px) {
.wrapper {
grid-template-columns: 1fr 1fr 1fr 1fr;
}
}
请务必在新标签中打开此演示,并更改视口大小以查看响应式效果!

因此,grid-template-columns
属性比我在这里显示的要复杂得多,但这是一个很好的起点。 接下来,我们应该了解 CSS Grid 规范中真正具有变革意义的属性:grid-template-rows
。
好的,让我们盲目地进行。 在下面的少量代码中,以及我们迄今为止对 Grid 的了解,让我们弄清楚这个新属性可能的作用
.wrapper {
display: grid;
grid-template-columns: 3fr 1fr 1fr;
grid-template-rows: 1fr 3fr;
}
我们现在将设置行的高度及其相互关系,而不是设置列的宽度及其相互关系。 因此,如果我们像在之前的演示中那样有两行,并且最后一个单位设置为 3fr,则表示第二行的高度始终是第一行的三倍
查看 CodePen 上 Robin Rendle (@robinrendle) 编写的 Type Specimen Grid Demo – 8。
这看起来可能很简单,但以前我们从未真正能够做到这一点。 我们总是不得不编写诸如在特定元素上设置min-height
或更改类名之类的粗略 hack。 但是我们以前从未能够像这样在行之间创建关系;这就是 CSS Grid 如此强大的原因。
凭借这些微不足道的知识和少量的新属性,我们可以创建非常复杂的布局——非对称和响应式网格只是其中的一小部分。 到目前为止,这仅仅是对庞大的 CSS Grid 规范的一瞥,因为还有很多内容需要介绍。 但我认为 Jen Simmons 在她关于 Grid 的文章中对其描述得最好
我们需要探索 CSS Grid,直到我们理解它想要做什么、它可以被强制做什么以及它拒绝做什么。 许多设计师可能永远不会学习编写 CSS 代码,但您需要充分了解 CSS 以理解我们的艺术媒介。
当然,上面所有的代码起初看起来都很奇怪。 但这意味着我们不必使用巨大的 CSS 框架,并且现在一大堆布局 hack 完全变得无关紧要了。 但真正让我对 Grid 感到兴奋的是,它迫使我们以一种全新的方式看待浏览器内部的空间。
我们不仅必须学习大量的新属性,而且还必须彻底重新思考我们过去学到的知识。 因此,CSS Grid 不仅仅是一个规范,而是一种独特的哲学。
让我们一起弄清楚吧!
浏览器支持
此浏览器支持数据来自Caniuse,其中包含更多详细信息。 数字表示浏览器在该版本及更高版本中支持该功能。
桌面
Chrome | Firefox | IE | Edge | Safari |
---|---|---|---|---|
57 | 52 | 11* | 16 | 10.1 |
移动/平板电脑
Android Chrome | Android Firefox | Android | iOS Safari |
---|---|---|---|
127 | 127 | 127 | 10.3 |
更多信息
- Jen Simmons 和 Rachel Andrew 撰写了许多关于此主题的精彩教程和演练
- Firefox 中的网格检查器工具非常方便
- 我们有一篇关于Grid 的完整指南,其中详细介绍了每个属性和值。
请原谅我提出的基本问题,但为什么依赖每个浏览器公司构建支持(并保持更新)比包含一个 CSS 文件更好呢?
我使用的是 Chrome 56,在更新到 57 之前,演示都没有正常工作。在 Firefox 中,情况相同。在更新之前,没有演示可以正常工作。我还有 IE11。它们也不工作,我假设以后也不会。
糟糕。那应该说永远不会。
你是指 JavaScript 文件(polyfill)吗?
包含一个用于 CSS Grid 的 CSS 文件根本不会有任何作用,因为旧版浏览器甚至都不理解 CSS Grid。如果浏览器不理解 CSS,它会根据设计跳过它。
你必须更新 Chrome 和 Firefox 的原因是,只有最新版本支持 CSS Grid。
实际上,这是一个合理的问题,尽管我不确定我是否是回答这个问题的合适人选,因为我对现代网页设计的了解都是书本知识。它主要归结于这样一个事实:CSS Grid(标准)比非 CSS Grid 的 CSS 实现的网格系统灵活得多。
它可以轻松实现一些难以或无法使用网格系统实现的效果,而无需添加大量样板代码、JavaScript 或假设。据我了解,它尤其允许源代码顺序与页面本身的定位无关,无论是在垂直方向还是水平方向。
它还可以实现尺寸关系,其中参考“单元格”的尺寸由内容的流动方式决定,而不是预先计算。使用传统的网格系统可以很容易地制作每个演示的示例,但这是因为这些演示都可以轻松地预先计算。想象一下,尝试设置类似于以下内容的东西,其中单元格的内容基于用户输入,因此你不能只说“此上下文的高度为 X*3,使其高度是另一个上下文高度 X 的三倍”。
基本上,本文是对 CSS Grid 的介绍,它并没有真正深入探讨 CSS Grid 可以执行的一些更高级的功能。它也没有强调 CSS Grid 可以使用任意内容执行此操作,并根据需要调整网格大小以平衡网格。是的,CSS 可以提供有关单元格如何增长和相互推动的提示和规则。
哦,天哪,直到我看到你的评论,我都很困惑。我以为我读错了,但事实证明我的 Chrome 没有像我想象的那样自动更新。更新后,它看起来大不相同,并且有意义(显然),但我同意你的观点,作为开发人员,我们将不得不为几代人提供 CSS 中的回退方案,在这种情况下,你可能希望暂时放弃 CSS Grid,直到几代浏览器淘汰。
在此期间,它让我想起了使用 srcset 用于图片。这很乏味且令人沮丧,当不得不参与其中时,我有时想打东西,但最终它确实带来了更好的整体网络体验。
CSS Grid 替换了 FlexBox 吗?
CSS Grid 不会替换 Flexbox。它们可以一起使用。了解何时使用哪一个的最简单方法之一是
对于一维布局(例如水平或垂直布局)使用 Flexbox。
对于二维布局(例如声明水平和垂直布局的样式)使用 CSS Grid。
因此,你可以使用 CSS Grid 创建页面布局,然后在该布局内的单个元素上使用 Flexbox。
如果需要,你甚至可以嵌套网格。
根本不是,它只是实现并共享了一些属性。它们可以一起工作。
Grid 和 FlexBox 不是相互排斥的。它们是用于不同工作的不同工具,就像汽车和卡车或手锯和台锯一样。你可以使用它们来完成类似的布局,但它们各有其优势。
Grid 用于全局排列,而 flexbox 适用于表示项目。
对于单页应用程序:Grid 用于站点布局,而 flexbox 用于内部列表项。
你的 caniuse 数据不正确。该链接指向这些关于 CSS Grid 支持的统计数据。
Firefox:52+(刚刚发布)
Chrome:57+(刚刚发布)
Safari:10.1(测试版)
IE:11+,但使用的是旧版本的规范。
Edge:当前版本仍在使用旧版本的规范。
iOS Safari:尚未支持。
Android:不支持。
许多人对提供的浏览器支持数据做出了回应。
这些数据确实来自 **CanIUse…** 并且是最新的,但我同意它有点令人困惑,因为它列出了第一个甚至部分支持 Grid 的浏览器。
原始数据位于此处:https://github.com/Fyrd/caniuse/blob/master/data.json
Rachel Andrews 有一个用简单的英语编写的浏览器支持页面:http://gridbyexample.com/browsers/
在 caniuse 数据中,“p”不是“部分支持”,而是“由 polyfill 支持”(在 caniuse.com 上未使用)。
https://github.com/Fyrd/caniuse/issues/665
在此处详细了解 caniuse 语法。
https://github.com/Fyrd/caniuse/blob/master/CONTRIBUTING.md
啊,是的!说得好。我修改了我们的后端代码以忽略“p”值。
我期待它能尽快在移动浏览器上得到支持!
在尝试掌握 CSS Grid 时,我复制了你的代码并尝试了不同的单位。你能否告知为什么即使我通过 PrePros 获取了正确的前缀,它在 Edge 中也没有正确显示?唯一显示的框是最后一个。在 Edge 中查看 CodePen – http://codepen.io/anon/pen/BWdLej
子网格可能吗?