CSS 网格布局的最佳实践
已发表: 2022-03-10一个越来越普遍的问题——现在人们在生产中使用 CSS 网格布局——似乎是“什么是最佳实践?” 这个问题的简短回答是使用规范中定义的布局方法。 您选择使用的规范的特定部分,以及您如何将 Grid 与其他布局方法(如 Flexbox)结合起来,取决于您尝试构建的模式以及您和您的团队希望如何工作。
更深入地看,我认为这种对“最佳实践”的要求可能表明对使用与以前截然不同的布局方法缺乏信心。 也许担心我们将 Grid 用于它不是为它设计的东西,或者在我们应该使用的时候不使用 Grid。 也许归结为对支持旧浏览器的担忧,或者 Grid 如何融入我们的开发工作流程。
在本文中,我将尝试介绍一些可以被描述为最佳实践的事情,以及一些您可能不需要担心的事情。
该调查
为了帮助了解这篇文章,我想了解其他人是如何在生产中使用网格布局的,他们面临的挑战是什么,他们真正喜欢什么? 是否有共同的问题、问题或使用的方法。 为了找出答案,我进行了一项快速调查,询问人们如何使用网格布局,特别是他们最喜欢什么以及他们认为具有挑战性的问题。
在接下来的文章中,我将引用并直接引用其中一些响应。 我还将链接到许多其他资源,您可以在其中找到有关所描述技术的更多信息。 事实证明,在调查回复中,有很多有趣的东西需要解开。 我将在以后的帖子中讨论其他一些问题。
可访问性
如果您在使用时需要注意 Grid 规范的任何部分,那就是在使用任何可能导致内容重新排序的内容时:
“作者必须将 order 和 grid-placement 属性仅用于视觉上的,而不是逻辑上的内容重新排序。 使用这些功能执行逻辑重新排序的样式表是不合格的。”
— 网格规范:重新排序和可访问性
这不是 Grid 独有的,然而,在二维中如此轻松地重新排列内容的能力使得 Grid 面临更大的问题。 但是,如果使用任何允许内容重新排序的方法——无论是 Grid、Flexbox 还是绝对定位——你需要注意不要将视觉体验与文档中的内容结构脱节。 屏幕阅读器(以及仅使用键盘在文档中导航的人)将遵循源中项目的顺序。
需要特别小心的地方是在 Flexbox 中使用flex-direction
反转顺序的时候; Flexbox 或 Grid 中的order
属性; 使用任何方法放置网格项目,如果它将项目移出文档中的逻辑顺序; 并使用grid-auto-flow
的密集包装模式。
有关此问题的更多信息,请参阅以下资源:
- 网格布局和可访问性 - MDN
- Flexbox 和键盘导航断开连接
我应该使用哪些网格布局方法?
“在 Grid 中有这么多的选择,坚持一致的编写方式是一个挑战(例如,是否命名网格线,定义网格模板区域,后备,媒体查询)以便它可以由整体维护团队。”
— 米歇尔·巴克
当您第一次看到 Grid 时,它可能看起来有很多不同的创建布局的方法。 然而,归根结底,这一切都归结为从网格的一条线到另一条线的定位。 您可以根据要实现的布局以及适合您的团队和正在构建的站点的布局进行选择。
没有正确或错误的方法。 下面,我将介绍一些常见的混淆主题。 在之前的文章“网格陷阱和绊脚石”中,我也已经介绍了许多其他潜在的混淆领域。
我应该使用隐式还是显式网格?
您使用grid-template-columns
和grid-template-rows
定义的网格称为显式网格。 显式网格允许命名网格上的线,还使您能够使用-1
定位网格的结束线。 您将选择一个 Explicit Grid 来做这些事情中的任何一个,并且通常当您设计了一个布局并且确切地知道您的网格线应该去哪里以及轨道的大小时。
我最常将隐式网格用于行轨道。 我想定义列,但是行将自动调整大小并增长以包含内容。 您可以使用grid-auto-columns
和grid-auto-rows
在某种程度上控制隐式网格,但是,与定义所有内容相比,您的控制权更少。
您需要确定是否确切知道您拥有多少内容以及行数和列数——在这种情况下,您可以创建一个显式网格。 如果您不知道您有多少内容,而只是想要创建的行或列来容纳所有内容,您将使用隐式网格。
不过,可以将两者结合起来。 在下面的 CSS 中,我在 Explicit Grid 中定义了三列和三行,所以前三行内容如下:
- 高度至少为 200 像素的轨道,但会扩展以使内容更高,
- 固定在 400px 高度的轨道,
- 高度至少为 300 像素的轨道(但会扩展)。
任何进一步的内容都将进入在隐式网格中创建的行中,我正在使用grid-auto-rows
属性使这些轨道至少 300px 高,扩展为auto
。
.grid { display: grid; grid-template-columns: 1fr 3fr 1fr; grid-template-rows: minmax(200px auto) 400px minmax(300px, auto); grid-auto-rows: minmax(300px, auto); grid-gap: 20px; }
具有灵活列数的灵活网格
通过使用重复符号、自动填充和 minmax,您可以创建一个包含尽可能多的轨道的模式,以适应容器,从而在一定程度上消除对媒体查询的需要。 这个技术可以在这个视频教程中找到,也可以在我最近的文章“在 2018 年使用媒体查询进行响应式设计”中与类似的想法一起演示。
如果您乐于在空间较小时将内容降到较早的内容之下,并且乐于在大小上提供很大的灵活性,请选择此技术。 您特别要求您的列以最小尺寸显示,并自动填充。
调查中有一些评论让我怀疑人们是否在真正想要具有固定列数的网格时选择了这种方法。 如果您在某些断点处得到不可预测的列数,您可能会更好地设置列数——并根据需要使用媒体查询重新定义它——而不是使用auto-fill
或auto-fit
。
我应该使用哪种轨道尺寸方法?
我在文章“那个盒子有多大?”中详细描述了轨道尺寸。 了解网格布局中的大小,”然而,我经常会遇到关于使用哪种轨道大小调整方法的问题。 特别是,有人问我百分比大小和fr
单位之间的区别。
如果您只是按照规定使用fr
单位,那么它与使用百分比不同,因为它分配了可用空间。 如果您将较大的项目放入轨道中,则fr
until 的工作方式是允许该轨道占用更多空间并分配剩余的内容。
.grid { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px; }

要使fr
单元分配网格容器中的所有空间,您需要使用minmax()
为其指定最小大小为0
。
.grid { display: grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr) minmax(0,1fr); grid-gap: 20px; }

因此,您可以选择在以下任一场景中使用fr
:您确实希望根据 auto 进行空间分配(默认行为),以及您希望平均分配的场景。 我通常会使用fr
单元,因为它会为您计算尺寸,并允许使用固定宽度的轨道或间隙。 我唯一使用百分比的时候是当我将网格组件添加到也使用其他布局方法的现有布局中时。 如果我希望我的网格组件与使用百分比的基于浮动或 flex 的布局对齐,那么在我的网格布局中使用它们意味着所有内容都使用相同的大小调整方法。

自动放置物品或设置它们的位置?
您经常会发现您只需要在布局中放置一两个项目,其余的根据内容顺序就位。 事实上,这是一个非常好的测试,你没有断开源和视觉显示。 如果事情几乎基于自动放置就位,那么它们可能处于良好状态。
然而,一旦我决定了所有事情的去向,我确实倾向于为所有事情分配一个位置。 这意味着如果有人在文档中添加了一些东西并且网格会自动将其放置在一个意想不到的地方,我不会最终发生奇怪的事情,从而丢弃布局。 如果所有内容都已放置,Grid 会将该项目放入下一个可用的空网格单元格中。 这可能不是您想要的位置,但在布局的最后坐下可能比跳到中间并推动其他东西要好。
使用哪种定位方法?
使用网格布局时,最终一切都归结为将项目从一行放置到另一行。 其他一切本质上都是帮助者。
与您的团队一起决定是否要命名线条、使用网格模板区域,或者是否要使用不同类型布局的组合。 我发现我特别喜欢将网格模板区域用于小型组件。 然而,没有对错之分。 找出最适合您的方法。
网格与其他布局机制相结合
请记住,网格布局并不是一个真正的布局方法来统治它们,它是为某种类型的布局而设计的——即二维布局。 其他布局方法仍然存在,您应该考虑每种模式以及最适合的模式。
我认为这对于我们这些习惯于使用布局方法来让他们做一些他们不是真正为之设计的事情的人来说实际上是相当困难的。 现在是退后一步的好时机,看看它们设计任务的布局方法,并记住将它们用于这些任务。
特别是,无论我多久写一次关于 Grid 与 Flexbox 的文章,都会有人问我应该使用哪一个。 有许多模式,其中任何一种布局方法都非常有意义,这完全取决于您。 没有人会因为您选择 Flexbox over Grid 或 Grid over Flexbox 而大喊大叫。
在我自己的工作中,我倾向于将 Flexbox 用于我希望项目的自然大小来强烈控制其布局的组件,本质上是推动其他项目。 我也经常使用 Flexbox,因为我想要对齐,因为 Box Alignment 属性只能在 Flexbox 和 Grid 中使用。 我可能有一个带有一个子项的 Flex 容器,以便我可以对齐该子项。
Flexbox 可能不是我应该选择的布局方法的一个迹象是,当我开始为 flex 项目添加百分比宽度并将flex-grow
设置为 0 时。为 flex 项目添加百分比宽度的原因通常是因为我试图对齐它们在二维中排列(在二维中排列正是 Grid 的用途)。 但是,两者都试一下,看看哪一个似乎最适合内容或设计模式。 这样做不太可能导致任何问题。
嵌套网格和弹性项目
这也经常出现,将 Grid Item 设为 Grid Container 绝对没有问题,从而将一个网格嵌套在另一个网格中。 你可以对 Flexbox 做同样的事情,制作一个 Flex Item 和 Flex Container。 您还可以将 Grid Item 和 Flex Container 或 Flex Item 设为 Grid Container — 这些都不是问题!
我们目前不能做的是将一个网格嵌套在另一个网格中,并让嵌套网格使用在整个父级上定义的网格轨道。 这将非常有用,也是网格规范第 2 级中的子网格提案希望解决的问题。 嵌套网格当前成为新网格,因此您需要小心调整大小以确保它与任何父轨道对齐。
一页上可以有多个网格
调查中出现了几次让我感到惊讶的评论,似乎有一个想法应该将网格限制在主要布局中,并且一页上的许多网格可能不是一件好事。 您可以拥有任意数量的网格! 对大事和小事使用网格,如果将其布置为网格有意义,则使用网格。
回退和支持旧浏览器
“与@supports 结合使用的网格使我们能够更好地控制我们可以预期看到的布局变化的数量。 它还与我们的渐进增强方法配合得非常好,这意味着我们可以奖励那些使用现代浏览器的人,而不会阻止那些不使用最新技术的人访问内容。”
——乔·兰伯特(Joe Lambert)在rareloop.com 上工作
在调查中,许多人提到了旧版浏览器,但是,由于功能查询和 Grid 覆盖其他布局方法的事实,认为支持旧版浏览器很难的人和认为支持旧浏览器容易的人之间存在相当大的差距。 我在“使用 CSS 网格:支持没有网格的浏览器”中详细介绍了创建这些后备的机制。
一般来说,现代浏览器比早期的浏览器更具有互操作性。 我们往往会看到更少的实际“浏览器错误”,如果您正确使用 HTML 和 CSS,那么您通常会发现您在一个浏览器中看到的内容与在另一个浏览器中看到的内容相同。
当然,我们确实有这样的情况,其中一个浏览器还没有提供对某个规范或某个规范的某些部分的支持。 使用 Grid,我们非常幸运,因为浏览器在很短的时间内以非常完整且可互操作的方式提供了 Grid Layout。 因此,我们对测试的考虑往往是需要测试有 Grid 和没有 Grid 的浏览器。 您可能还选择在 IE10 和 IE11 中使用-ms
前缀版本,这需要作为第三种类型的浏览器进行测试。
支持现代网格布局(不是 IE 版本)的浏览器也支持特征查询。 这意味着您可以在使用之前测试网格支持。
测试不支持网格的浏览器
当为不支持网格布局的浏览器使用回退(或为 IE10 和 11 使用-ms
前缀版本)时,您将需要测试这些浏览器如何呈现网格布局。 为此,您需要一种在示例浏览器中查看站点的方法。
我不会通过检查是否支持无意义的东西或拼写错误的值来破坏您的功能查询的方法grid
。 这种方法只有在您的样式表非常简单并且您已经将与网格布局有关的所有内容都放在功能查询中时才有效。 这是一种非常脆弱且耗时的工作方式,尤其是在您广泛使用 Grid 的情况下。 此外,旧版浏览器不仅不支持网格布局,还会不支持其他 CSS 属性。 如果您正在寻找“最佳实践”,那么设置自己,以便您能够很好地测试您的工作,那就是高高在上!
有几种简单的方法可以让你自己设置一个合适的方法来测试你的后备。 最简单的方法——如果你有相当快的互联网连接并且不介意支付订阅费——是使用诸如 BrowserStack 之类的服务。 这是一项服务,可让您在整个主机上的真实浏览器上查看网站(甚至是您计算机上正在开发的网站)。 BrowserStack 确实为开源项目提供免费帐户。

要在本地进行测试,我的建议是使用安装了目标浏览器的虚拟机。 Microsoft 提供免费的虚拟机下载,其中 IE 版本回到 IE8 和 Edge。 您还可以在 VM 上安装完全不支持 Grid 的旧版浏览器。 例如,通过获取 Firefox 51 或更低版本的副本。 安装旧版 Firefox 后,请务必按照此处的说明关闭自动更新,否则它会自动更新!
然后,您可以在一个 VM 上在 IE11 和不支持的 Firefox 中测试您的站点(这是一个比拼写错误值更脆弱的解决方案)。 设置可能需要你一个小时左右,但你将在一个非常好的地方测试你的后备。
忘掉旧习惯
“这是我第一次使用网格布局,所以有很多概念要学习,属性要理解。 从概念上讲,我发现最难忘记我多年来所做的所有事情,比如清理浮动和将所有东西打包到容器 div 中。”
— 隐藏在 hiddedevries.nl/en 上的工作
许多对调查做出回应的人提到需要摒弃旧习惯,以及对于完全不熟悉 CSS 的人来说学习 Layout 会变得更容易。 我倾向于同意。 面对面教学时,初学者使用 Grid 几乎没有问题,而有经验的开发人员则努力将网格恢复为一维布局方法。 我已经看到使用 CSS Grid 的“网格系统”尝试添加回基于浮动或基于 flex 的网格所需的行包装器。
不要害怕尝试新技术。 如果您有能力在几个浏览器中进行测试并注意潜在的可访问性问题,那么您真的不会错得太远。 而且,如果您找到了创建特定模式的好方法,请让其他人知道它。 我们都是在生产中使用 Grid 的新手,所以肯定有很多东西可以发现和分享。
“网格布局是自媒体查询以来最令人兴奋的 CSS 开发。 它经过深思熟虑,可以满足实际开发人员的需求,并且在生产中使用绝对是一种乐趣——对于设计师和开发人员来说都是如此。”
— Trys Mudford 在 trysmudford.com 上工作
总结一下,这是一个非常简短的当前最佳实践列表! 如果您发现在您自己的情况下效果很好或效果不佳的事情,请将它们添加到评论中。
- 非常注意内容重新排序的可能性。 检查您是否没有断开视觉显示与文档订单的连接。
- 使用带有本地或远程虚拟机的真实目标浏览器进行测试。
- 不要忘记旧的布局方法仍然有效且有用。 尝试不同的方法来实现模式。 不要因为不得不使用 Grid 而挂断电话。
- 要知道,作为一名经验丰富的前端开发人员,您可能对布局的工作原理有一整套先入之见。 尝试重新审视这些新方法,而不是强迫它们回到旧模式。
- 继续尝试。 我们都是新手。 测试您的工作并分享您的发现。