一些匹配设计模型的 CSS Grid 策略

Avatar of Chris Geelhoed
Chris Geelhoed on

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

网络开发领域一直存在着 设计到开发交接的差距。有抱负的设计师希望他们努力的最终结果看起来独特而美丽(并符合他们最初的愿景),而许多开发人员发现一致、可靠且坚如磐石(并且易于编码)的结果更有价值。这种动态会导致双方之间持续的紧张局势,双方都希望以自己的方式引导事物。

虽然这种情况在某种程度上是不可避免的,但新的前端技术可以在将双方拉近方面发挥作用。其中一项技术就是 CSS Grid。这篇文章探讨了如何使用它来编写 CSS 样式,以高度保真地匹配设计布局(没有头痛!)。

设计师向前端开发人员提供说明的一种常见方式是使用设计模型(通过模型,我们指的是在 Sketch、XD、Illustrator、Photoshop 等中构建的交付成果)。所有设计师在某种程度上都以不同的方式工作(开发人员也是如此),但许多设计师喜欢将他们布局的结构基于某种网格系统。一致的网格系统对于传达网页的编码方式以及用户屏幕大小不同于模型时网页的响应方式至关重要。作为一名开发人员,我非常感谢那些努力采用经过深思熟虑的网格系统的设计师。

12 列布局特别受欢迎,但其他模式也很常见。像 Sketch 和 XD 这样的软件使得创建遵循预设列布局的页面变得非常容易 - 你可以点击一个按钮来切换叠加层。

在 Sketch(左)和 Adobe XD(右)中设计的网格布局

一旦实施了网格系统,大多数设计元素都应正方形地放置在其中。这种方法确保形状均匀对齐,并呈现出更具吸引力的外观。除了视觉上的吸引力之外,可预测的网格还为开发人员在编写样式时提供了明确的目标。

不幸的是,这种基本模式可能具有欺骗性的难以准确编码。像 Bootstrap 这样的框架通常用于创建网格布局,但它们也有一些缺点,例如增加了页面重量和缺乏细粒度的控制。CSS Grid 为前端完美主义者提供了一个更好的解决方案。让我们看一个例子。

14 列网格布局

上面的设计是网格的一个很好的应用。它有一个 14 列的模式,其中包含多个元素。虽然这些框都具有不同的宽度和偏移量,但它们都遵循相同的网格。这个布局可以用 flexbox 甚至浮动来制作 - 但这可能需要一些非常具体的数学来在所有断点上获得像素完美的結果。让我们面对现实吧:许多前端开发人员都没有耐心这样做。让我们看看三种用于更轻松地完成此类工作的 CSS 网格布局策略。

策略 1:基本网格

查看 CodePen 上的
基本网格放置
by chris geel (@RadDog25)
on CodePen.

编写均匀间隔的 12 列布局的最直观方法可能是这个的变体。这里,使用外部容器来使用左右填充控制外部间隙间距,并且使用内部行元素来将内容限制在最大宽度。该行接收一些特定于网格的样式

display: grid;
grid-template-columns: repeat(12, 1fr);
grid-gap: 20px;

此规则定义网格由 12 列组成,每列的宽度为 一个分数单位 (fr)。还指定了列之间 20px 的间隙。设置列模板后,可以使用 grid-column 属性非常轻松地设置任何子列的开始和结束位置。例如,设置 grid-column: 3/8 会将该元素定位在第三列开始,跨越五列到第八列。

我们已经看到 CSS Grid 在这个例子中提供的许多价值,但这种方法有一些局限性。一个问题是 Internet Explorer 不支持 grid-gap 属性。另一个问题是,这种 12 列方法不提供在间隙的末尾开始列或在间隙的开头结束列的能力。为此,需要另一个系统。

策略 2:更灵活的网格

查看 CodePen 上的
更灵活的网格放置
by chris geel (@RadDog25)
on CodePen.

虽然 grid-gap 可能是 IE 的禁忌,但可以通过将空格作为网格模板本身的一部分来重新创建间隙的外观。grid-template-columns 可用的 repeat 函数不仅接受单个列宽度作为参数,还接受任意长度的重复模式。为此,可以将列-然后-间隙模式重复 11 次,然后插入最后一列以完成所需的 12 列 / 11 内部间隙布局

grid-template-columns: repeat(11, 1fr 20px) 1fr;

这解决了 IE 问题,并且还允许在列或间隙的开头和结尾处开始和结束列。虽然这比以前的方法有了很大的改进,但它仍然有很大的改进空间。例如,如果要将一列定位在一侧跨越到屏幕的外部边缘,而另一侧适合网格系统?这是一个例子

带有与外部边缘齐平的项目的网格布局

在这个布局中,卡片(我们的左列)在网格内开始和结束。主图像(我们的右列)也从网格内开始,但延伸到网格之外,到达屏幕边缘。为其编写 CSS 可能是一个挑战。一种方法可能是绝对定位图像并将其固定到右边缘,但这有一个缺点,即将其从文档流中取出(如果图像比卡片更高,这可能是一个问题)。另一个想法是使用浮动或 flexbox 来保持文档流,但这将需要一些棘手的单次计算才能使宽度和间距恰到好处。让我们看看一个更好的方法。

策略 3:更灵活的网格

查看 CodePen 上的
右边缘对齐的图像与网格
by chris geel (@RadDog25)
on CodePen.

此技术建立在上次修订中介绍的想法之上。现在,我们不是让网格存在于定义间隙大小和行宽度的其他元素中,而是将这些空格与网格的模式集成在一起。由于间隙、列和间隙都包含在模板中,因此可以使用 grid-column 属性轻松而精确地将子元素定位在网格上。

$row-width: 1140px;
$gutter: 30px;
$gap: 20px;
$break: $row-width + 2 * $gutter;
$col-width-post-break: ($row-width - 11 * $gap) / 12;
  
.container {
  display: grid;
  grid-template-columns: $gutter repeat(11, calc((100% - 2 * #{$gutter} - 11 * #{$gap})/12) #{$gap}) calc((100% - 2 * #{$gutter} - 11 * #{$gap})/12) $gutter;
  @media screen and (min-width: #{$break}) {
    grid-template-columns: calc(0.5 * (100% - #{$row-width})) repeat(11, #{$col-width- post-break} #{$gap}) #{$col-width-post-break} calc(0.5 * (100% - #{$row-width}));
  }
}

是的,需要一些数学运算才能使它完全正确。重要的是在实现行最大宽度之前和之后以不同的方式设置模板。我选择为此使用 SCSS,因为定义变量可以使计算更易于管理(更不用说对其他开发人员更易读)。最初的 12 部分模式随着 11 个内部间隙的集成而增长到 23 部分模式,现在有 25 个部分,分别代表左右间隙。

这种方法的一件很酷的事情是,一旦模式设置好,它就可以用作遵循网格的任何布局的基础,包括传统上难以处理的布局,这些布局涉及跨越到外部边缘的列。此外,它提供了一种直接的方法来精确地实施可能以高质量模型形式传递的设计。这应该让开发人员和设计师都感到高兴!

有一些注意事项…

虽然这些技术可以用来解决传统上难以处理的样式问题,但它们不是灵丹妙药。相反,应该将它们视为用于正确应用的替代工具。

第二和第三种布局模式不适合的一种情况是需要自动放置的布局。另一种情况是需要支持不支持 CSS Grid 的浏览器的生产环境。