grid-template-areas

Avatar of Mojtaba Seyedi
Mojtaba Seyedi on

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

grid-template-areas CSS 属性允许您定义和命名 CSS 网格容器中的单元格(或“区域”)。

.grid-container {
  display: grid;
  grid-template-areas: "header header" "sidebar main";
}

因此,上面的示例?我们得到一个 2x2 的网格,其中顶行保留两列,用于名为 header 的区域。底行也得到两列,但分别保留给名为 sidebarmain 的网格区域。

Two by two grid of squares.

这意味着我们已经建立了网格,并且已经定义了网格区域,但实际上没有将任何内容分配给这些网格区域。如果我们想将元素放置在网格区域中,我们必须使用该元素上的 grid-area 属性明确声明它。

.grid-container {
  display: grid;
  grid-template-areas: "header header" "sidebar main";
}
.grid-header {
  grid-area: header;
}
.grid-sidebar {
  grid-area: sidebar;
}
.grid-content {
  grid-area: main;
}

需要注意的是,网格区域必须是网格容器中的单个单元格,或者是一组相邻的单元格,且必须是 **矩形**。这意味着以下所有示例都是有效的。

Two valid and valid examples of grid areas.
这些绿色部分是有效网格模板区域的示例。

但我们无法做到的是形成非矩形的网格区域。因此,如果您要定义的区域更像是“T”形或“L”形,那么就无能为力了。

Two invalid examples of grid-template-areas.

语法

grid-template-areas: none | <string>
  • 初始值:none
  • 应用于:网格容器
  • 继承:
  • 计算值:如指定,关键字 none 或字符串值列表
  • 动画类型:离散

/* Keyword value */
grid-template-areas: none;

/* <string> values */
grid-template-areas: "col-1 col-2 col-3";
grid-template-areas: "header header header" "sidebar main main";
grid-template-areas: "header header header"
                      "sidebar main main"
                      ". footer footer";

/* Global values */
grid-template-areas: inherit;
grid-template-areas: initial;
grid-template-areas: revert;
grid-template-areas: unset;

none

这是 **默认** 值。正如您可能猜到的,none 表示没有在网格容器上设置命名的网格区域和显式网格轨道。这也意味着 网格轨道是隐式生成的,它们的大小由 grid-auto-columnsgrid-auto-rows 属性定义。

除了使用 grid-template-areas 之外,实际上还有另一种创建显式网格轨道的方法,那就是使用 grid-template-columnsgrid-template-rows 属性。我们将在本文后面更详细地介绍这一点。

<string>

字符串可以是您想要为特定网格模板区域指定的任何名称。因此,如果您的网格容器中有一行,并且您希望布局的标题放在那里,您可以将该区域命名为“header”或“page-top”,或者您想要的任何名称。实际上,如果该行中有多列,我们可以将每一列都命名为不同的网格区域。

.grid {
  grid-template-areas: "logo menu utility-nav";
}

请注意,该示例中的整个三列行都被括在引号中。这一点至关重要,因为用引号括起来的命名网格模板区域表示新行。因此,如果我们有两行,我们将看到两组引号区域。

.grid {
  grid-template-areas: "logo menu utility-nav" "sidebar-1 content sidebar-2";
}

更妙的是,我们可以通过将每一行写在自己的行上来使这一点更容易理解。

.grid {
  grid-template-areas:
    "logo menu utility-nav"
    "sidebar-1 content sidebar-2";
}

字符串的语法可以实现跨越和跳过网格容器中的单元格等功能。我们稍后会讲到这一点。

基本用法

首先,让我们使用父网格容器上的 grid-template-areas 属性来定义网格模板区域。

.grid {
  display: grid;
  grid-template-areas:
    "header header header"
    "sidebar main main"
    "footer footer footer";
}

目前,网格容器已命名区域,但其中没有任何内容。要将元素放置在其中,我们需要使用要放置的元素上的 grid-area 属性将命名的网格区域分配给该元素。

header {
  grid-area: header;
}

aside {
  grid-area: sidebar;
}

main {
  grid-area: main;
}

footer {
 grid-area: footer;
}

这是根据我们在父网格容器上定义的 grid-template-areas 获得的结果。

A webpage layout created using the CSS `grid-template-areas` property

调整网格命名区域的大小

可以使用父网格容器上的 grid-template-columnsgrid-template-rows 属性设置网格轨道的尺寸。

假设我们有一个布局要求,我们的网格需要两列,第二列占用的空间是第一列的两倍。我们可以使用 分数 (fr) 单位 来实现这一点。

.grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr 2fr;
  grid-template-areas: "sidebar main";
}

对于行来说也是一样的。假设我们现在需要在 3x3 的网格中实现以下布局。

A webpage layout created using the CSS grid-template-areas property

这一次,我们将第一行和第三行设置为 250px 的固定高度,但调整中间行的尺寸,使其占用内容所需的空间。

.grid {
  display: grid;
  gap: 1rem;
  grid-template-rows: 250px auto 250px;
  grid-template-areas:
    "header header header"
    "sidebar main main"
    "footer footer footer";
}

如果您想知道所有这些重复的命名网格模板区域是怎么回事,那是因为......

跨越单元格和行

重复命名区域可以连接单元格。因此,如果目标是创建一个名为 feature 的命名区域,并使其占用顶行中的两列,我们可以执行以下操作。

/* Valid declaration */
grid-template-areas: "feature feature widget";

很酷,如果同一命名区域在每一行都开始,我们也可以在垂直方向上执行类似的操作。

/* Valid declaration */
grid-template-areas:
  "feature aside widget-1"
  "feature aside widget-2";

当然,我们可以将两者结合起来,创建一个跨越两个方向的网格模板区域。

/* Valid declaration */
grid-template-areas:
  "feature feature widget-1"
  "feature feature widget-2";

如前所述,网格模板区域必须是矩形的。这意味着以下最后一个示例的变体无效。

/* Invalid declaration */
grid-template-areas:
  "feature feature widget-1"
  "feature aside widget-2";

我们可以在单元格之间创建间隙(或硬“停止”)

可以使用点 (.) 符号来实现这一点。

grid-template-areas:
  "header header header"
  "sidebar main main"
  ". footer footer"; /* first cell is empty */
}

点的数量无关紧要。我们可以这样做。

grid-template-areas:
  "header  header header"
  "sidebar main   main"
  "....... footer footer"; /* first cell is empty */
}

这两个声明都创建了相同的网格。

由于点符号的存在,第三行中的第一列为空。

空白是可视化网格的好方法

以下声明是等效的,但第二个声明更容易可视化网格的结构,因为我们使用空空白来对齐名称。

grid-template-areas:
  "header header header"
  "sidebar main main"
  ". footer footer";

grid-template-areas:
  "header  header header"
  "sidebar main   main"
  ".       footer footer";

如果您正在寻找另一种可视化网格容器的方法,Chris 有一个巧妙的想法,即在 CSS 注释中使用 ASCII 格式“绘制”网格,以便在 CSS 注释中使用 ASCII 格式“绘制”网格,以便快速参考。.

行必须具有相同数量的列

所有列表必须具有相同数量的值,否则声明无效。

/* 👍 */
grid-template-areas:
  "name name-2 name-3"
  "name name-2 name-3"
  "name name-2 name-3";

/* 👍 */
grid-template-areas:
  "header header"
  ". main"
  "footer footer";

/* 👎 */
grid-template-areas:
  "name name-2 name-3"
  "name name-2 name-3"
  "name name-3";

使用 Unicode 字符命名网格区域

根据规范,任何不符合 <ident> 语法的名称,在其他属性中按名称引用该区域时都需要转义。 例如,在下面的声明中,第一个区域的名称以数字开头,因此不符合 <ident> 语法。

.grid {
  grid-template-areas: "1st b c";
}

解决方法是声明 1 数字的未转义 十六进制代码。在本例中,十六进制代码为 U+0031,我们在 CSS 中将其转义为 \31st。因此,我们使用它将元素分配到该命名网格区域。

.grid-item {
  grid-area: \31st;
}

隐式分配的线名称

使用 grid-template-areas 属性定义轨道,我们可以根据分配的名称免费获得线名称。这与 grid-template-rowsgrid-template-columns 属性不同,在定义列和行时,我们需要提供线名称。grid-template-areas 属性并非如此,因为它会获取我们提供的名称,并为我们输出轨道名称。

每个网格模板区域名称都会创建四条网格线。如果我们有一个名为 sidebar 的网格模板区域,我们将获得两对名为 sidebar-startsidebar-end 的轨道线——一对用于列方向,一对用于行方向。

Showing track lines in a CSS grid layout created with grid-template-areas.

您可能想知道,如果我们显式定义轨道名称,并使用与隐式定义相同的名称——例如显式定义名为 sidebar-start 的网格线用于名为 sidebar 的区域会发生什么?两条线可以共存并被分配给不同的元素。换句话说,显式值仍然有效,并且两条线都可以使用。

隐式命名区域

在网格容器中命名网格区域的另一种方法是,在设置 grid-template-columnsgrid-template-rows 属性上的轨道名称时,让 CSS 网格为我们隐式命名它们。

我们只需要为网格区域选择一个名称,并在其后面添加 -start-end 作为轨道名称。例如,在这里,我们得到一个名为 sidebar 的网格模板区域,甚至没有声明 grid-template-areas 属性。

.grid-container {
  display: grid;
  grid-template-columns: [sidebar-start] 250px [sidebar-end] 1fr;
}

aside {
  grid-area: sidebar;
}

如上例所示,虽然没有 grid-template-areas 属性显式定义名为“sidebar”的区域,但该区域仍然可以通过网格放置属性(如 grid-areagrid-rowgrid-column 或其完整写法)进行引用。

示例:响应式圣杯布局

在以下演示中,我们使用 grid-template-areas 属性 使用 CSS 网格创建著名的圣杯布局

此布局之所以得名,是因为在 使用浮动进行布局 的时代,它难以置信地难以实现。谢天谢地,我们有了 CSS 网格,使它几乎微不足道。

首先,我们的 HTML

<div class="grid">
  <header>Header</header>
  <main>Main Content</main>
  <aside class="left-sidebar">Left Sidebar</aside>
  <aside class="right-sidebar">Right Sidebar</aside>
  <footer>Footer</footer>  
</div>

到目前为止很简单,对吧?我们希望标题位于顶部,页脚位于底部,并且主要内容位于中间行的三列之一。

我们可以在 CSS 中设置命名网格模板区域,并在需要时跨行。

.container {
  grid-template-columns: 12rem auto 12rem;
  grid-template-areas:
    "header header header"
    "left-sidebar main right-sidebar"
    "footer footer footer";    
}

现在我们需要将每个元素分配到一个命名网格区域。

header {
  grid-area: header;
}
main {
  grid-area: main;
}
footer {
  grid-area: footer;
}
.left-sidebar {
  grid-area: left-sidebar;
}
.right-sidebar {
  grid-area: right-sidebar;
}

嗯,我们实际上完成了!这就是全部。我们可以通过默认情况下垂直堆叠网格区域,然后在更大的屏幕上构建圣杯布局来更进一步,在那里它看起来好多了。

.container {
  display: grid;
  grid-template-areas:
    /* Each area is a row */
    "header"
    "nav"
    "article"                       
    "sidebar"                           
    "footer";
}

@media (min-width: 600px) {
  .container {
    grid-template-columns: 12rem auto 12rem;
    grid-template-areas:
      /* Build the Holy Grail layout */
      "header header header"
      "nav article article"
      "sidebar article article"
      "footer footer footer";
  }
}

浏览器支持

更多信息

更多技巧!