CSS 网格 - 表格布局恢复正常。立足于正方形

要点

如果您熟悉 Flexbox,就会对 Grid 感到熟悉。 Rachel Andrew 保持着非常好的 专门介绍 CSS 网格的网站 。网格功能现在可在 Google Chrome 中使用。

Flexbox?网格?

在过去的几年里,CSS Flexbox 已得到广泛使用, 浏览器支持看起来非常棒 (除非您是不得不支持 IE9 及更低版本的可怜鬼之一)。 Flexbox 简化了许多复杂的布局任务,例如等距间距 自上而下布局或 CSS 高手的制胜法宝: 垂直居中。

无法跨多个 Flexbox 容器对齐元素。

但唉,屏幕通常还有一个我们需要关注的第二个维度。 如果没有自行调整元素的大小,很遗憾, 同时满足竖屏和横屏节奏。这是 CSS 网格就能派上用场了

CSS 网格一直在开发中,在大多数浏览器中, 5 年内,我们投入了额外的时间来提升互操作性,以避免 像 Flexbox 一样有漏洞的发布。如果您使用 Grid 通过 Chrome 浏览器,您在 Firefox 和 Safari 中可能得到相同的结果。在 则 Microsoft Edge 的 Grid 实施版本已过时( 与 IE11 中已有相同)。更新 “正在考虑”中。

尽管 Flexbox 和 Grid 在概念和语法上很相似,但 相互竞争的布局技术网格按二维排列,而 Flexbox 布局在一个位置两者结合使用可产生协同效应。

定义网格

要熟悉 Grid 的各个属性,我强烈建议您 Rachel Andrew 的 Grid By Example 或 CSS Tricks' 备忘单。如果您 Flexbox 的很多属性及其含义

我们来看一个标准的 12 列网格布局。传统的 12 列 布局很受欢迎,因为数字 12 可以被 2、3、4 和 6 整除, 因此在许多设计中非常有用我们来实现此布局:

无法跨多个 Flexbox 容器对齐元素。

我们先从标记代码开始:

<!DOCTYPE html>
<body>
    <header></header>
    <nav></nav>
    <main></main>
    <footer></footer>
</body>

在样式表中,我们首先扩展 body,使其涵盖整个 并将视口转换为网格容器

html, body {
    width: 100vw;
    min-height: 100vh;
    margin: 0;
    padding: 0;
}
body {
    display: grid;
}

现在我们使用 CSS 网格太棒了!

下一步是实现网格的行和列。我们可以 在模型中实现全部 12 列,但由于我们没有使用每一列, 这会使我们的 CSS 显得杂乱无章。为简单起见, 我们将按以下方式实现布局:

简化布局示例

页眉和页脚的宽度可变,内容也可变 两个维度。导航栏在两个维度中都是可变的 将最小宽度设置为 200px(为什么?为了展示 CSS 网格。)

在 CSS 网格中,这组列和行称为轨道。我们先来 定义我们的第一组轨道,即行:

body {
    display: grid;
    grid-template-rows: 150px auto 100px;
}

grid-template-rows 采用一系列定义各行的大小。 在本例中,我们为第一行指定 150 像素的高度,为最后一行指定 100 像素的高度。 中间行设置为 auto,这意味着它会调整为必要的 高度以容纳网格项网格容器的子项) 该行。由于我们的正文横跨整个视口,因此轨迹 至少会填满 但是如果达到该空间,它会增加(并使文档滚动) 。

对于列,我们希望采用更具动态性的方法:我们希望同时提供导航和 但我们希望导航栏始终不要缩小到 200px 以下 并且希望内容比导航栏大在 Flexbox 中,我们使用“flex-grow” flex-shrink,但在 Grid 中则略有不同:

body {
    display: grid;
    grid-template-rows: 150px auto 100px;
    grid-template-columns: minmax(200px, 3fr) 9fr;
}

我们要定义 2 列。第一列使用 minmax() 定义 函数,其值有 2 个值:曲目的最小值和最大值。 (就像 min-widthmax-width 合二为一。)最小宽度为 也就是 200px宽度上限为 3frfr 是特定于网格的 可让您向网格元素分配可用空间的单元。 fr 可能代表“fraction unit”,但也可能表示免费单元。 这里的值意味着两列都会变大并填满整个屏幕, 内容列的宽度始终为导航列的 3 倍(前提是 nav 列的宽度始终大于 200px)。

虽然网格项的位置尚不正确,但网格项的大小 行和列的行为正确,产生我们想要的行为:

放置商品

Grid 最强大的功能之一是能够在没有 DOM 顺序的概念(不过,由于屏幕阅读器会在 DOM 中进行导航, 因此,为了能够正常访问各项内容 对元素进行重新排序)。如果未手动放置元素,系统会将元素放置 网格中按 DOM 顺序排列,从左到右、从上到下排列。每个元素 占用一个单元格。可以使用 grid-auto-flow

那么,我们如何放置元素呢?放置网格项的最简单方法是 定义它们所覆盖的列和行。Grid 提供了两种语法来实现这一点: 在第一个语法中,您需要定义起点和终点。在您定义的第二个 起点和跨度:

header {
    grid-column: 1 / 3;
}
nav {
    grid-row: 2 / span 2;
}
手动设置展示位置

我们希望标题从第一列开始,并在第三列之前结束。 导航应从第二行开始,总共跨越 2 行。

技术上,我们已经完成了布局的实现 网格提供的便捷功能,可让您更轻松地放置展示位置。通过 第一项功能是为路线的边界命名 并用这些名称 展示位置:

body {
    display: grid;
    grid-template-rows: 150px [nav-start] auto 100px [nav-end];
    grid-template-columns: [header-start] minmax(200px, 3fr) 9fr [header-end];
}
header {
    grid-column: header-start / header-end;
}
nav {
    grid-row: nav-start / nav-end;
}

上面的代码将产生与之前代码相同的布局。

更强大的功能是为网格中的整个区域命名:

body {
    display: grid;
    grid-template-rows: 150px auto 100px;
    grid-template-columns: minmax(200px, 3fr) 9fr;
    grid-template-areas: "header header"
                        "nav    content"
                        "nav    footer";
}
header {
    grid-area: header;
}
nav {
    grid-area: nav;
}

grid-template-areas 接受一个以空格分隔的名称字符串,允许 为每个单元格命名如果两个相邻单元格的名称相同, 它们会聚集到同一个区域这样,您就可以 语义,并使媒体查询更直观。同样, 代码会生成和之前相同的布局。

还有其他问题吗?

是的,确实有太多内容,一篇博文要介绍。 Rachel AndrewGDE,是受邀用户 CSS 工作组专家,从一开始就与他们合作 以确保 Grid 可以简化网页设计。她甚至还写了 图书。她的 Grid By Example 网站是非常有价值的 帮助您熟悉 Grid。很多人认为网格 革命的 但现在 Chrome 已默认启用该功能 使用它。