图解 5 种布局掌握 CSS Grid

1,615 阅读7分钟

翻译:布兰 作者:Thu Nghiem 阅读原文

网格是一个工具,你可以使用它来帮助你的网站创建布局。如果你需要考虑不同元素的位置、层次或大小,它就特别有用。

网格是复杂的,有很多东西要学习。但好消息是,你不需要一下子知道所有的事情。

在本教程中,我们将使用 CSS Grid 构建 5 种不同的布局(下面将解释为 5 个独立的任务)。

下面是我们将要构建的前两个布局:

任务1 和 任务2

1. 如何用 CSS 网格构建煎饼堆栈

对于任务一,我们需要创建一个煎饼堆布局。要创建这个布局,我们可以使用 grid-template-rows: auto 1fr auto 创建三行。值为 1fr 的第二行将尽可能扩展,而其他两行通过包装其内容只有足够的空间。

所以为了实现这个布局,我们所要做的就是给容器提供以下参数:

.task-1.container {
    display: grid;
    height: 100vh;
    
    grid-template-rows: auto 1fr auto;
}

2. 如何使用 CSS Grid 创建一个简单的 12 列网格布局

基本的12列网格布局一直沿用至今。使用 CSS Grid,它甚至更容易使用。在这个简单的任务中,我们需要给项目 1 四列和项目 2 六列。

首先,我们需要创建 12 列,可以使用 grid-template-columns: repeat (12,1fr) :

.task-2.container {
    display: grid;
    height: 100vh;
    
    grid-template-columns: repeat(12, 1fr);
    column-gap: 12px;
    
    align-items: center;
}

注意这里我们还有每列之间 12px 的间隙。与 Flex 类似,我们也可以使用 align-itemsjustify-content

接下来我们需要做的是告诉项目应该占用哪一栏:

对于第1项,我们希望它从第 2 栏开始,到第 6 栏结束。所以我们有:

.task-2 .item-1 {
  grid-column-start: 2;
  grid-column-end: 6;
}

请注意,该项目不包括第 6 列,只包括第 2、3、4 和 5 列。

我们也可以通过如下代码产生同样的影响:

.task-2 .item-1 {
    grid-column-start: 2;
    grid-column-end: span 4;
}

或者是这样:

.task-2 .item-1 {
    grid-column: 2 / span 4;
}

按照同样的逻辑,我们将对项目 2 作如下说明:

.task-2 .item-2 {
    grid-column: 6 / span 6;
}

3. 如何使用或不使用 grid-template-areas 建立一个响应式布局

在这里,我将向你们展示两种选择,即使用或者不使用 grid-template-areas。对于第一个选项,我们将使用从第二个任务中学到的 12 列网格。对于第二个选项,我们将使用一个名为 grid-template-areas 的属性。

第一个选项: 如何使用 12 列网格

移动设备

这很简单。我们可以利用从第一个任务中学到的知识,扩展主要部分。我们也可以给网格一个空白: 24px,就像在桌面上一样。将有列,而不仅仅是行:

.task-3-1.container {
    display: grid;
    height: 100vh;
    
    grid-template-rows: auto auto 1fr auto auto auto;
    gap: 24px;
}

平板电脑

对于屏幕宽度超过 720px 的平板电脑电脑,我们希望有 12 列 4 行。第三行将尽可能扩大:

@media (min-width: 720px) {
    .task-3-1.container {
        grid-template-columns: repeat(12, 1fr);
        grid-template-rows: auto auto 1fr auto;
    }
}

现在我们有了 12 列,我们需要告诉每个项目应该占用多少列:

@media (min-width: 720px) {
    .task-3-1 .header {
        grid-column: 1 / span 12;
    }
    
    .task-3-1 .navigation {
        grid-column: 1 / span 12;
    }
    
    .task-3-1 .main {
        grid-column: 3 / span 10;
    }
    
    .task-3-1 .sidebar {
        grid-column: 1 / span 2;
        grid-row: 3;
    }
    
    .task-3-1 .ads {
        grid-column: 1 / span 2;
    }
    
    .task-3-1 .footer {
        grid-column: 3 / span 10;
    }
}

注意这里我们需要给 .task-3-1 .sidebar: grid-row: 3; 因为侧边栏在 DOM 的主要部分之后。

桌面

对于桌面视图,我们将使用大于 1020px 的屏幕。因为我们已经有了 12 列,现在我们只需要告诉它应该使用多少列:

@media (min-width: 1020px) {
    .task-3-1 .navigation {
        grid-column: 3 / span 8;
    }
    
    .task-3-1 .main {
        grid-column: 3 / span 8;
    }
    
    .task-3-1 .sidebar {
        grid-column: 2 / 4;
    }
    
    .task-3-1 .ads {
        grid-column: 11 / span 2;
        grid-row: 2 / 4;
    }
    
    .task-3-1 .footer {
        grid-column: 1 / span 12;
    }
}

第二个选择: 如何使用 grid-template-areas

在使用 grid-template-areas 之前,我们需要使用 grid-area 来定义项目的区域:

.task-3-2 .header {
    grid-area: header;
}

.task-3-2 .navigation {
    grid-area: nav;
}

.task-3-2 .ads {
    grid-area: ads;
}

.task-3-2 .sidebar {
    grid-area: sidebar;
}

.task-3-2 .main {
    grid-area: main;
}

.task-3-2 .footer {
    grid-area: footer;
}

在项目区域被定义之后,我们所要做的就是通过使用 grid-template-areas 来给容器定位。

移动设备

.task-3-2.container {
    display: grid;
    height: 100vh;
    
    gap: 24px;
     
    grid-template-rows: auto auto 1fr auto auto auto;
    
    grid-template-areas:
        "header"
        "nav"
        "main"
        "sidebar"
        "ads"
        "footer";
}

所以在移动设备上,我们创建了 1 列和 6 行。第三行,也就是主行,应该尽可能地扩展。

如果稍后您想要更改项目的顺序/位置,这也使得更改变得更加容易。例如,如果我们想要在头部之前有导航,我们可以这样做:

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

平板电脑

@media (min-width: 720px) {
    .task-3-2.container {
    grid-template-rows: auto auto 1fr auto;
      
    grid-template-areas:
        "header header header"
        "nav nav nav "
        "sidebar main main"
        "ads footer footer";
    }
}

使用上面的代码,如果屏幕宽度大于 720px,我们希望创建 3 列 4 行。标题和导航都占据了 3 列。

在第三行和第四行,侧边栏和广告占一栏,而主页和页脚占两栏。

桌面

@media (min-width: 1020px) {
    .task-3-2.container {
    grid-template-rows: auto auto 1fr auto;
      
    grid-template-areas:
        "header header header header"
        "sidebar nav nav ads"
        "sidebar main main ads"
        "footer footer footer footer";
    }
}

在这里,我们发现了与平板电脑视图类似的逻辑。对于桌面,我们创建了 4 列和 4 行,并根据 grid-template-areas 的值进行布局。

两个选项该如何选择

使用 12 列网格优缺点

  • 简单和快速的开始;
  • 易于维护的列为中心的布局;
  • 难以安排项目在复杂的布局;

你应该使用12列的网格布局,这些布局不是很复杂,主要集中在列的排列上。

使用 grid-template-areas 的优缺点

  • 灵活的复杂布局;
  • 易于可视化;
  • 需要更多的时间来实现;

对于更复杂的布局,您应该使用 grid-template-areas,在这些布局中,您需要关注许多元素的位置或大小。

这两个选项都有利有弊,但是你应该选择一个对你来说更简单,并且在你的特定场景中更有意义的选项。

4. 如何在 CSS 网格中构建一个没有媒体查询的响应式布局

做到这一点出人意料地简单。我们可以用一行代码来实现,像这样:

.task-4.container {
    display: grid;
    gap: 24px;
    
    grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

我们刚刚创建了一个灵活的列布局,并指定该列不应小于 150px,并且应该均匀地共享空间。

5. 如何使用 CSS Grid 构建一个 12 x 12 的象棋网格

对于最后一个任务,我想向您展示,我们不仅可以定义列的数量,而且还可以使用 CSS Grid 定义行的数量。

.task-5.container {
    display: grid;
    height: 100vh;
    
    grid-template-columns: repeat(12, 1fr);
    grid-template-rows: repeat(12, 1fr);
}

现在,我们可以把项目放在任何我们想要的地方:

...
.task-5 .item-1 {
    grid-row: 1 / span 3;
    grid-column: 1 / span 3;
}

.task-5 .item-2 {
    grid-row: 4 / span 3;
    grid-column: 4 / span 3;
}

.task-5 .item-3 {
    grid-row: 7 / span 3;
    grid-column: 7 / span 3;
}

.task-5 .item-4 {
    grid-row: 10 / span 3;
    grid-column: 10 / span 3;
}