CSS 网格:图解介绍 简介 1. 开始之前 2. CSS 网格基本属性 3. 高级模板 4. 隐式行和网格流 结论

2025-05-25

CSS Grid:图文介绍

介绍

1. 开始之前

2. CSS网格基本属性

3. 高级模板

4. 隐式行和网格流

结论

这篇文章是两部分系列文章中的第一部分。


介绍

我还记得第一次学习 CSS 时的兴奋,当时我迫不及待地想学习浮动和内联显示,以便将元素按所需的布局放置。我当时很好奇,如果当时有一套二维布局系统,我会作何反应。实际上,即使是现在,我仍然对此感到兴奋,因为它改变了一切:不仅改变了我们编写 CSS 的方式,也改变了我们编写标记的方式。有了 CSS 网格,构建响应式、动态且不受源码顺序影响的布局比以往任何时候都更加容易。

在本文中,我们将学习所有 CSS 网格属性,以构建简单布局和一些不太简单的布局。我们将对所有内容进行定义,然后深入探究 CSS 网格可以实现哪些功能。
话虽如此,如果您准备好学习一种新的布局思维方式,那就吞下红色药丸吧,我将带您探索这个兔子洞的深度。

矩阵红色药丸选择

1. 开始之前

但在开始之前,我想解决您可能存在的一些问题,并确保我们熟悉 CSS 网格及其术语的基础知识。

问答

CSS 网格会取代弹性框吗?

其实,CSS 网格并不能取代 flex-box。它们是两种不同的工具,用于不同的目的。实际上,它们可以很好地协同工作,我们可以在网格显示内使用 flex 显示,反之亦然。

CSS 网格和弹性框之间有什么区别?

它们之间有很多区别,但最主要的一点是 flex-box 是一个一维布局系统,而 CSS grid 是一个二维布局系统。请看下面的图 1.1

网格图像

图 1.1:弹性盒与 CSS 网格

为什么不使用 bootstrap 来代替呢?

我认为这个问题的最佳答案是 Jen Simmons 的这句话:

我使用 CSS Grid 越多,就越确信在其上添加一层抽象层没有任何好处。CSS Grid 是嵌入浏览器的布局框架。—— Jen Simmons

CSS 网格是否已准备好投入生产?

视情况而定。您需要支持:IE、Opera mini、黑莓浏览器还是百度移动?如果答案是否定的,那么它已经可以投入生产了;如果答案是肯定的,那么在支持它的浏览器(无前缀浏览器:91.61%)上,您可以使用@supportsCSS at 规则使用它:

@supports (display: grid) {
  div {
    display: grid;
  }
}
Enter fullscreen mode Exit fullscreen mode

基础知识

基本上,网格可以分解为两个元素:网格容器网格项

网格图像

图 1.2:基本网格

如图 1.2所示,网格容器是一组列和行。Arow是两条连续的行线(水平线)之间的空间,acolumn是两条连续的列线(垂直线)之间的空间。行可以称为轨道,列也可以称为轨道。因此,网格track是两条平行网格线之间的空间。

每个轨道可以包含一个或多个网格单元。网格cell是最小的网格单元,也是最基本的网格单元。它是四条相交网格线之间的空间。如果我们将多个网格单元组合在一起,就得到了一个网格area。需要注意的是,网格区域必须是矩形,例如不能是T形网格区域。

网格线数从 1 开始,直到您显式或隐式定义的线数。最后一个网格线数可以表示为 -1,其前一个网格线数可以表示为 -2,依此类推。这在后面会用到。在图 1.2
,列线数从 1 到 6(或从 -6 到 -1),行线数从 1 到 5(或从 -5 到 -1)。

explicit如果您在 CSS 中明确设置了网格线的数量,则会考虑网格线的数量。implicit如果由浏览器动态设置,也会考虑网格线的数量。

最后,网格单元之间可以用空格或间隙分隔。这些间隙称为gutters,但我们通常将其称为gaps:)。

2. CSS网格基本属性

好了,现在我们可以开始实现一些网格了。首先,我们将讨论网格容器的所有可用属性,然后再看看网格项的属性。

让我们考虑本节的以下模板:

<div class="grid-container">
    <div class="grid-item">grid item 1</div>
    <div class="grid-item">grid item 2</div>
    <div class="grid-item">grid item 3</div>
    <div class="grid-item">grid item 4</div>
    <div class="grid-item">grid item 5</div>
    <div class="grid-item">grid item 6</div>
    <div class="grid-item">grid item 7</div>
    <div class="grid-item">grid item 8</div>
    <div class="grid-item">grid item 9</div>
</div>
Enter fullscreen mode Exit fullscreen mode

网格容器

展示

CSS 网格是使用属性grid值定义的display。因此,要使用上面的模板定义网格,我们应该这样做:

.grid-container {
  display: grid;
}
Enter fullscreen mode Exit fullscreen mode

行和列

grid-template-rows我们可以使用和属性定义网格上的列和行grid-template-columns

.grid-container {
  grid-template-columns:  1fr 1fr 1fr 1fr;
  grid-template-rows:  1fr auto 2fr;
}
Enter fullscreen mode Exit fullscreen mode

或者我们可以使用grid-template首先定义grid-template-rows然后定义grid-template-columns(以斜线分隔)的地方:

.grid-container {
  grid-template:  1fr auto 2fr  / 1fr 1fr 1fr 1fr;
}
Enter fullscreen mode Exit fullscreen mode

顺便说一下,anfr是一个分数单位,所以1fr是可用空间的 1 部分。

重复功能

repeat()函数表示曲目列表的重复片段。
因此,我们可以像这样实现与上面相同的模板:

.grid-container {
  grid-template:  1fr auto 2fr / repeat(4, 1fr);
}
Enter fullscreen mode Exit fullscreen mode

阅读此处的文档以了解如何使用auto-fitauto-fill动态添加曲目。

最小最大函数

CSS函数minmax()定义了一个大于或等于 min 且小于或等于 max 的尺寸范围。
我们可以repeat()像这样使用它:

.grid-container {
  grid-template-columns:  repeat(3, minmax(100px, 1fr));
}
Enter fullscreen mode Exit fullscreen mode

差距

我们可以使用 在行线之间添加间隙row-gap,我们可以使用 在列线之间执行相同操作column-gap

.grid-container {
 row-gap: 5px;
 column-gap: 10px;
}
Enter fullscreen mode Exit fullscreen mode

或者我们可以使用gap首先定义row-gap然后定义的column-gap

.grid-container {
  gap: 5px 10px;
}
Enter fullscreen mode Exit fullscreen mode

如果行距与列距相同,则只能指定一个值。

网格项目

为了指定网格项在网格中的起始和终止位置,我们主要使用四个属性。让我们看看它们的定义。

定义

特性 定义
grid-row-start grid-row-start CSS 属性通过提供一条线、一个跨度或什么都不提供(自动)来指定网格项在网格行内的起始位置
grid-row-end grid-row-end CSS 属性通过提供一条线、一个跨度或什么都不提供(自动)来指定网格项在网格行内的结束位置
grid-column-start grid-column-start CSS 属性通过提供一条线、一个跨度或什么都不提供(自动)来指定网格项在网格列内的起始位置
grid-column-end grid-column-end CSS 属性通过提供一条线、一个跨度或什么都不提供(自动)来指定网格项在网格列内的结束位置

或者我们可以使用这些属性的缩短版本:

特性 定义
grid-row grid-row CSS 属性是 grid-row-start 和 grid-row-end 的简写属性,用于指定网格项在网格行内的大小和位置
grid-column grid-column CSS 属性是 grid-column-start 和 grid-column-end 的简写属性,用于指定网格项在网格列中的大小和位置

基本模板间距

那么,考虑到我们在本节开头的标记,假设我们希望第三个网格项占用 4 个单元格而不是 1 个单元格(我们希望它跨越两个网格列和两个网格行),就像图 1.3中那样。我们该怎么做呢?

模板间距

图 1.3:模板间距示例

我们可以这样实现:

// Grid container
.grid-container {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(3, 1fr);
}

// Grid item (third)
.grid-container .grid-item:nth-child(3) {
  grid-column-start: 1;
  grid-column-end: 3;
  grid-row-start: 1;
  grid-row-end: 3;
  // or
  grid-column: 1 / 3;
  grid-row: 1 / 3;
  // or
  grid-column: 1 / span 2;
  grid-row: 1 / span 2;
  // or
  grid-column: -5 / span 2; // because we have 4 columns
  grid-row: -4 / span 2; // because we have 3 rows
}
Enter fullscreen mode Exit fullscreen mode

请注意,图 1.3中第三个网格项实际上是第一个。这与 CSS 网格首次实现了源顺序独立性有关。稍后讨论 时会稍微讨论这一点grid-auto-flow

如果您想试用并探索不同的解决方案,请单击此处。

3. 高级模板

还有更多高级属性可以帮助您根据需要调整模板。在本节中,我们将研究这些属性,并了解如何在 CSS 中使用它们。

对于本节,请考虑以下模板:

 <div class="grid-container">
   <div class="grid-item header">Header</div>
   <div class="grid-item content">Content</div>
   <div class="grid-item navbar">Navbar</div>
   <div class="grid-item meta">Meta</div>
   <div class="grid-item footer">Footer</div>
 </div>
Enter fullscreen mode Exit fullscreen mode

利用我们之前学到的知识,我们可以实现以下 CSS,使其看起来像一个基本的网站布局:

.grid-container {
  grid-template: repeat(6, 1fr) / repeat(12, 1fr);// rows then columns
}
.grid-container .header {
  grid-column: 1 / -1;  grid-row: 1 / 2;
}
.grid-container .navbar {
  grid-column: 1 / 2;  grid-row: 2 / -1;
}
.grid-container .content {
  grid-column: 2 / -1;  grid-row: 2 / -2;
}
.grid-container .footer {
  grid-column: 2 / -1;  grid-row: -2 / -1;
}
.grid-container .meta {
  grid-column: -3 / -1;  grid-row: 2 / 4;
}
Enter fullscreen mode Exit fullscreen mode

基本布局

图 1.4:网站基本布局。代码可在此处获取

现在假设我们希望右侧的导航栏稍微宽一点。目前,它横跨一列线,我们希望它横跨两列线。为此,我们必须更改 的位置,.navbar但也必须更改.content和 的.footer位置,因为目前.navbar是从第一列线到第二列线,而 &.footer.content从第二列线到最后一列线。

如果每次都要修改元素的位置,那会很繁琐。如果有一种方法可以让 CSS 网格自动帮我们完成这项工作,那就太好了。嗯,方法不止一种,但至少有两种。

命名行

第一个解决方案是为特定的线路命名,然后使用其别名而不是其编号来引用它。让我们尝试实现这一点。

.grid-container {
  grid-template-rows: repeat(6, 1fr);
  grid-template-columns: 1fr 1fr [content-start navbar-end] repeat(10, 1fr);
}
Enter fullscreen mode Exit fullscreen mode

在上面的代码中,我们使用简单的括号命名了第三行,并在括号内添加了别名(一行代码可以有多个别名)。接下来,我们将修改前面提到的元素的 CSS:

.grid-container .navbar {
  grid-column: 1 / navbar-end;  grid-row: 2 / -1;
}
.grid-container .content {
  grid-column: content-start / -1;  grid-row: 2 / -2;
}
.grid-container .footer {
  grid-column: content-start / -1;  grid-row: -2 / -1;
}
Enter fullscreen mode Exit fullscreen mode

结果应该如下所示:
扩展导航栏

图 1.5:基本网站布局 - 扩展导航栏

尝试对此代码片段中的其他行(例如:header-row-end / content-row-start)执行相同操作

元素模板区域

第二种解决方案是使用模板区域。CSSgrid-template-areas属性指定命名的网格区域。此属性的 CSS 语法比较奇怪,但我们可以使用如下方式:

.grid-container {
  grid-template-areas:
    'h h h h h h h h h h h h'
    'n n c c c c c c c c c c'
    'n n c c c c c c c c c c'
    'n n c c c c c c c c c c'
    'n n c c c c c c c c c c'
    'n n f f f f f f f f f f';
}
.grid-container .navbar {
  grid-area: n;
}
.grid-container .content {
  grid-area: c;
}
.grid-container .footer {
  grid-area: f;
}
.grid-container .header {
  grid-area: h;
}
.grid-container .meta {
  grid-column: -3 / -1;  grid-row: 2 / 4;
}
Enter fullscreen mode Exit fullscreen mode

我们使用grid-template-areas来定义网格容器区域,然后使用 将网格项放置在所需的区域中grid-area
提醒一下,所有区域都必须是矩形。

注意我们没有使用grid-areafor .metaelement。这是因为目前还没有办法用这种方法来叠加元素。至少我目前还不知道。

您可以尝试一下,代码可以在这里找到

4. 隐式行和网格流

让我们考虑以下代码:

<div class="grid-container">
  <div class="grid-item">1</div>
  <div class="grid-item">2</div>
  <div class="grid-item">3</div>
  <div class="grid-item">4</div>
  <div class="grid-item">5</div>
  <div class="grid-item">6</div>
</div>
<style>
.grid-container {
  grid-template-columns: repeat(3, minmax(100px, 1fr));
  grid-template-rows: 80px;
}
.grid-container .grid-item:nth-child(2) {
  grid-row: span 2;
}
.grid-container .grid-item:nth-child(3) {
  grid-column: span 3;
}
</style>
Enter fullscreen mode Exit fullscreen mode

我们有一个三列的网格,我们希望第二个网格项跨越两行,第三个网格项跨越三列。结果如下:
坏网格

图 1.6 糟糕的网格

这看起来很糟糕,那么这里发生了什么?首先,第二个元素比第一个元素略高,因为我们设置它的高度是第一个元素的两倍,但它看起来根本没有高两倍。而且,从 3 到 6 的网格项比第一个元素的高度要低。

隐式行

这与我们显式设置第一行有关:grid-template-rows: 80px;。但其他行是隐式创建的,所以第二行几乎不可见,因为它是空的,而其他行的大小已根据其内容需要而定。
我们可以通过如下方式设置隐式创建的行的高度来解决这个问题grid-auto-rows

.grid-container {
  grid-template-columns: repeat(4, minmax(100px, 1fr));
  grid-template-rows: 80px;
  grid-auto-rows: 100px; 
} 
Enter fullscreen mode Exit fullscreen mode

这看起来应该是这样的:
更好的网格,但仍然

图 1.7 更好的网格,但仍然

这样看起来好多了,但我们还可以做得更好。注意到那些空白处,我们为什么不使用它们来放置网格项 4、5 和 6 呢?
为此,我们可以使用grid-auto-flow

网格流

CSSgrid-auto-flow属性控制自动放置算法的工作方式,指定自动放置的项目如何流入网格。它可以接受多个参数(您可以在此处阅读更多信息),但这里我们只关注一个:dense
这将告诉浏览器将项目放置在任何足够大的空间上:

.grid-container {
  grid-auto-flow: dense; // default is row
}
Enter fullscreen mode Exit fullscreen mode

这样我们的网格终于看起来漂亮了:)

好网格

图1.8 正确实现的网格

结论

这些信息量很大,但我们已经了解了 CSS 网格的许多属性,所以你应该可以轻松地在应用中使用 CSS 网格了。这篇文章是系列文章的第一篇,下一篇我们将使用网格实现三个实际示例,敬请期待。

我希望您学到一些有用的东西,并一如既往地祝您编码愉快!


嘿,我们保持联系吧!

我正在创作很多精彩的文章和教程。如果你喜欢这篇,记得在Twitter上关注我,这样就能及时了解下一篇的发布时间。


接下来读什么?

文章来源:https://dev.to/mustapha/css-grid-illusterated-introduction-52l5
PREV
我制作了一个可用的 Gameboy CSS 艺术作品:尝试一下🕹
NEXT
CSS 网格:3 个实用示例 简介 搜索过滤器 图片库 精美主页布局 总结