翻译日期:2020.4.6
作者:Anna Prenzel 2020.03.30

CSS 网格为我们提供了一个强大的网站布局系统。CSS-Tricks guide( https://css-tricks.com/snippets/css/complete-guide-grid/)通过布局示例,为您提供 Grid 属性的全面概述。我们这里将用最小的 grid 属性集合去满足您大多数的布局需求。

这五个属性将帮助你完成:

  • display(用于 grid 的值)
  • grid-template-columns
  • grid-gap
  • grid-auto-flow
  • grid-column / grid-row

假设你希望为小、中和大屏幕实现以下布局。
image.png小和中屏幕image.png大屏幕

我们的HTML这样写:

  1. <header></header>
  2. <nav class="container-nav">
  3. <ul>
  4. <li></li>
  5. <li></li>
  6. <li></li>
  7. <li></li>
  8. <li></li>
  9. <li></li>
  10. <li></li>
  11. <li></li>
  12. <li></li>
  13. </ul>
  14. </nav>
  15. <div class="container-main">
  16. <section class="item item-type-a"></section>
  17. <section class="item item-type-b"></section>
  18. <section class="item item-type-b"></section>
  19. <section class="item container-inner">
  20. <section class="item-inner"></section>
  21. <section class="item-inner"></section>
  22. <section class="item-inner"></section>
  23. <section class="item-inner"></section>
  24. <section class="item-inner"></section>
  25. </section>
  26. </div>
  27. <footer></footer>

如果我们应用一些基线样式,这就是我们所得到的,这对于小屏幕来说已经足够了。
具体代码

现在我们可以进入使用网格属性了。

使用 display:网格将页面划分为独立的布局容器

首先,我们需要确定页面的哪些部分应该与网格布局对齐。可以为整个页面定义单个网格布局。然而,对于结构非常复杂的网站(例如:新闻网站),处理一个大型网格很快就变得非常复杂。在这种情况下,我建议将内容分解成几个独立的网格容器。
像这样:
image.png

你如何区分什么是网格,什么不是网格?以下是我遵循的个人经验法则:

如果页面特定部分中的布局不适合页面相邻部分或周围部分的网格,则使该部分成为自己的网格容器。

我已经将网格线绘制到带有 .container-main 类的页面部分中,在下面的图像中,您可能会注意到标记中带有 .container-inner 类的部分与网格中的行并不完全匹配。

image.png

这里是另一种可能的布局,在这种布局中,如果选择了更细的线光栅,那么小的部分就适合周围的网格。这里不需要单独的网格容器。

image.png

首先,让我们将 .container-main 放到一个网格容器中。这是 CSS 网格的基本构件 —— 将元素转换为带有 display 属性的网格容器

  1. .container-main {
  2. display: grid;
  3. }

我们希望对其他网格容器做同样的事情:

  1. .container-inner {
  2. display: grid;
  3. }
  4. .container-nav {
  5. display: grid;
  6. }

使用 grid-template-columns 来定义所需的列

接下来,我们将定义每个网格容器中需要的列数以及这些列的宽度。我的列数指南:使用不同屏幕大小所需的最大列数的最小公倍数。

这是怎么做到的呢? .container-main 元素在中等大小的屏幕上总共有两列。如果我们用它乘以大屏幕上的列数(3),我们总共得到6列。

我们可以对导航,.container-inner 元素执行相同的操作。中型屏幕上有三列,我们将它们乘以大型屏幕上的一列,总共得到三列。

.container-nav 元素不提供任何列数。在这种情况下,网格系统应该根据菜单元素的数量自动调整列的数量。在导航栏中添加或删除项目是很常见的,如果它们相应地做出响应就太好了,这是网格稍后可以帮助我们做的事情。

我们定义了每个网格容器的列数。让我们使用 grid-template-columns 属性来设置它们。但是,首先有几个小细节:

  • grid-template-columns 属性仅用于网格容器中。换句话说,您不会发现它在容器内的网格项上被使用。
  • 属性接受一组不同的值,这些值定义列的数量和列的宽度。我们感兴趣的是分数(fr)单位。我强烈建议查看Robin的概述 https://css-tricks.com/introduction-fr-css-unit/,因为它是网格特有的,并且在决定网格元素如何适合于网格容器的计算方面做得非常好。

我们需要在 .container-main 中包含 6 个等宽的列。我们可以这样写:

  1. .container-main {
  2. display: grid;
  3. grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr;
  4. }

或者,我们可以使用 repeat() 函数将其简化为更具可读性的内容:

  1. .container-main {
  2. display: grid;
  3. grid-template-columns: repeat(6, 1fr);
  4. }

让我们将这些知识也应用到 .container-inner 元素中,我们决定需要三列。

  1. .container-inner {
  2. display: grid;
  3. grid-template-columns: repeat(3, 1fr);
  4. }

使用 grid-gap 来添加网格项之间的间距

默认情况下,网格使用网格容器中所有的空间来容纳网格项。让元素彼此齐平可能是一个设计需求,但不是我们所做的特定布局。我们需要一些喘气的空间!

我们有 grid-gap 属性做这件事。同样,这是一个仅用于网格容器的属性,它的作用是在网格项之间创建垂直和水平间距。它实际上是一个简写性质,它结合了垂直间距 grid-row-gap 和 水平间距 grid-column-gap。将水平间距和垂直间距分开写很方便实现,但是,在这种我们在每个方向上使用相同的间距的情况下, grid-gap 写起来更方便。

我们想要在 .container-main 中的网格项之间有 20px 的空间,在 .container-inner 中有 10px 的空间,在 .container-nav 中有 5px 的空间。没问题!它所需要的只是每个网格容器上的一行程序。

  1. .container-main {
  2. display: grid;
  3. grid-template-columns: repeat(6, 1fr);
  4. grid-gap: 20px;
  5. }
  6. .container-inner {
  7. display: grid;
  8. grid-template-columns: repeat(3, 1fr);
  9. grid-gap: 10px;
  10. }
  11. .container-nav {
  12. display: grid;
  13. grid-gap: 5px;
  14. }

注意:CSS Grid Layout 起初是用 _grid-gap_ 属性来定义的,目前逐渐被 _gap_ 替代。但是,为了兼容那些不支持gap 属性的浏览器。需要使用带有前缀的属性。

使用 grid-column 和 grid-row 确定各个网格项的大小

现在是时候把布局变成我们想要的形状了!

首先是 grid-column 属性,它允许我们将一个网格扩展到 n 个列,其中 n 是要跨越的列。如果您认为这听起来很像rowspan 属性,它允许我们跨 HTML 表中的多行扩展单元格,那么您不会错。

当我们在 .container-main 元素中的 .item.container-inner 中的 .inner-item 元素上使用它时,它看起来是这样的:

  1. .item {
  2. grid-column: span 6;
  3. }
  4. .item-inner {
  5. grid-column: span 3;
  6. }

这里我们说的是,每个项目在主容器中跨越 6 行,在内部容器中跨越 3 行——这是每个容器中列的总数。

注意:关于CSS网格的一个有趣的事情是我们能够命名网格的线条。它们有现成的隐式名称,但是命名它们是区分赛道上每一列的起始行和结束行非常有效的方法。

我们可以改变列和行数的项目应该跨越在不同的断点:

  1. @media screen and (min-width: 600px) {
  2. .item-type-b {
  3. grid-column: span 3;
  4. }
  5. .item-inner {
  6. grid-column: span 1;
  7. }
  8. }
  9. @media screen and (min-width: 900px) {
  10. .item {
  11. grid-column: span 2;
  12. grid-row: span 2;
  13. }
  14. .item-type-b{
  15. grid-row: span 1;
  16. }
  17. .item-inner{
  18. grid-column: span 3;
  19. }
  20. }

使用 grid-auto-flow 来控制元素的放置

CSS网格将元素一行接一行地放置,这就是我们的例子中的结果看起来是这样的:
image.png

可以通过将 grid-auto-flow 属性设置为 column(row是默认值)来实现逐列放置。我们的布局将从两种情况下的列式布局中获益。首先,它使我们的菜单项最终以水平方向显示。其次,它将容器类的元素放入所需的分组中。

最终结果
https://codepen.io/blaustern_fotografie/pen/MWwmjQL

结论:更多或更少的规范
网格系统允许我们按照“尽可能多地生成规范,但尽可能少地生成规范”的格言工作。我们只讨论了将元素转换为CSS网格容器和将其中的项转换为网格项所需的一些规范,以便说明使用CSS网格构建复杂布局所需的知识是多么的少。

CSS网格支持额外的用例:

  • 我们想做更少的规范,以取代更多的依赖自动定位。
  • 为了确定最终布局的更多细节,我们希望制定更多的规范。

如果第一种情况适用,那么值得考虑以下附加的网格选项:

  • 在创建带有 grid-template-columns的网格时,可以让网格系统使用 auto 关键字自动确定各个列的宽度,或者通过设置 min-content、max-content或fit-content使其适应现有内容。
  • 你可以让网格系统在repeat、auto-fill、auto-fit和minmax的帮助下自动确定所需列的数量。即使是媒体查询也会变得多余,这些工具可以使事情变得灵活,而不需要添加更多的媒体查询。

这里有几篇文章是我推荐的:成为一个CSS网格忍者! https://medium.com/@elad/becoming-a-css-grid-ninja-f4c6db018cc1和Auto-Sizing Columns in CSS Grid: auto-fill vs. auto-fit https://css-tricks.com/auto-sizing-columns-css-grid-auto-fill-vs-auto-fit/

如果第二种情况适用,CSS网格为你提供了更多设置选项:

  • 你可以使用 grid-template-columns 属性显式地指定所选单元中的列的宽度(例如px或%)。此外,如果有特定数量的行,可以使用 grid-template-rows 属性来定义行数和行宽。
  • 你还可以将特定的列号或行号定义为 grid-column 和 grid-row的值(或者使用grid-column-start、grid-column-end、grid-row-start或grid-row-end属性)。

我们甚至还没有进入 CSS网格对齐!尽管如此,我们可以在不涉及该主题的情况下完成如此多的工作,这一事实表明CSS网格是多么强大。

原文: https://css-tricks.com/4-css-grid-properties-and-one-value-for-most-of-your-layout-needs/

参考链接: