【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

如果你有多年的网站制作经验,你就会知道使用 CSS 浮动来布局网页是多么令人沮丧。管理尺寸和位置既繁琐又耗时。而且往往无法发挥创意。CSS Grid 2017 年推出了 Grid Level 1,现在又推出了 Grid Level 2(又名 Subgrid),大大缓解了这种痛苦。但是,即使有了如今强大的 CSS,也并非设计师想象的每一种布局都能实现。事实上,在 CSS Grid 发布之初,最常被问到的问题之一就是:”如何编写 CSS 来实现Masonry布局?”遗憾的是,在过去的七年中,答案一直是–你做不到。

什么是砌体 masonry 布局?

我们所说的 “Masonry布局 “是什么意思?基本上就是下图中的模式–内容像砖块或石墙一样堆积在一起。这就是 “Masonry “名称的由来。它也经常被称为 “瀑布式布局“,比喻内容像瀑布一样从页面上流下。

图0:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

这种布局之所以受欢迎,是因为它解决了一些其他布局无法解决的问题。

  • 它允许不同长宽比的内容,避免了为了把所有内容都变成统一的矩形而对内容进行裁剪或截断。
  • 它将内容分布在整个页面上(而不是一栏一栏地往下排)。这符合滚动页面时的自然阅读顺序。它还能让网站在底部懒散地加载其他内容,而无需移动现有内容。

这种布局创建了大小一致的列,没有任何行。很有可能因为这种布局需要 JavaScript,所以任何更有创意或更复杂的布局都很难实现,而我们也只能期望砌体布局只能是大小一致的列的简单模式。让我们看看,如果我们将其构建到 CSS 中,会有怎样的效果。

发明砌体 masonry 布局

2020 年 1 月,Mozilla 首次提出了 CSS 中的 “Masonry布局 “机制,作为 CSS Grid 的扩展,并在 Firefox Nightly 中作为一个标志进行了实验。2022 年,苹果开始在 Safari 技术预览版中实施这一 CSS Grid Level 3(目前默认开启),我们一直在帮助推动这一网络标准走向成熟。

然而,关于 CSS 应如何处理Masonry式布局,人们仍有很多疑问。有些人仍然怀疑这种功能是否应该成为 CSS 网格的一部分,而希望它成为自己独立的display类型。另一些人则质疑网络上是否需要这种布局–他们不确定知名网站是否会使用这种布局。有了这些根本性的分歧,任何浏览器都无法出货。我们必须首先在 CSS 工作组中达成共识。

这正是我们需要您帮助的地方。我们希望现实世界中的网页设计师和开发人员参与讨论,并表达你们的想法。您的意见将带来真正的改变。

在本文中,我们将介绍 CSS Grid Level 3 提案的工作原理,以及如何使用其新功能。我们会告诉你为什么我们认为这些功能应该成为 CSS 网格的一部分,并解释如果 CSS 工作组创建了 display: masonry,会有哪些替代方案。然后,我们会邀请你加入讨论,帮助我们取得进展。请务必读到最后。

四个演示

为了说明 Apple 为何认为 CSS Grid 中应包含这一功能,我们制作了四个演示。如果你想亲自体验,请访问 webkit.org/demos/grid3。请在支持 Grid Level 3 的浏览器中观看这些演示,当前浏览器为 Safari 技术预览版或打开功能标志后的 Firefox。

请注意,每个演示都有一个控制面板,相关的布局代码会打印到页面上。打开 “编号项”,查看 HTML 内容顺序与内容布局位置之间的关系。

图1:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

每个演示都有多种变化。通过下拉菜单在不同变化之间切换,只需更改 CSS 即可。HTML 保持不变。

图2:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

创建经典的Masonry/瀑布式布局

首先,让我们来看看如何创建经典的Masonry/瀑布布局。在这组照片中,每张图片都用一个figure 元素包裹,数字是main元素的直接子元素。

<main>
  <figure><img src="photo-1.jpg"></figure>
  <figure><img src="photo-2.jpg"></figure>
  <figure><img src="photo-3.jpg"></figure>
</main>

首先,我们在主元素上应用 display: grid 来创建网格容器。然后,我们就可以随意定义 grid-template-columns 了。

在本例中,我们使用 grid-template-columns: repeat(auto-fill,minmax(14rem,1fr))来要求浏览器重复循环定义,以创建一组最小为 14rem 的灵活列。这样就形成了大小一致的列,是典型的砌体/瀑布式布局。gap: 1rem; 规则在项目之间创建了 1rem 宽的空格–既包括列之间的空格,也包括项目之间的水平空格。

然后,我们将使用masonry 值定义 “rows”。(这个值的名称很可能会在浏览器发布之前发生变化,本文末尾会有详细介绍。目前,masonry “是可行的)。

main { 
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
  grid-template-rows: masonry;
}

grid-template-rows: masonry 规则会告诉浏览器”请不要创建行。而应将内容打包成砌体/瀑布模式”。

就是这样!只需四行 CSS,不需要任何媒体查询或容器查询,我们就能创建一个灵活的布局,适用于各种尺寸的屏幕。而且不需要裁剪内容,就能将所有内容强制放入相同大小的方框中。

图3:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

在平面设计中,大小一致的列而没有行的布局通常被称为 “对称列式网格”。几个世纪以来,列式网格一直是页面设计中使用的主要网格类型。

充分利用网格的全部功能来定义列

现在,让我们深入了解将 CSS 网格的全部功能与砌体/瀑布式包装相结合的优势。CSS 网格为我们定义网格列提供了多种选择。使用 fr 单位创建对称网格只是众多选项中的一种。

如何将这些可能性用于砌体/瀑布式布局呢?让我们尝试将固定大小的列与灵活的列混合使用。我们可以将第一列和最后一列设置为固定大小,而中间的列则是灵活的,可以改变大小和数量。

具体来说,第一列和最后一列的宽度正好是 14 个字符,而中间一列的宽度则比较灵活(至少 28 个字符),并可改变数量以填充可用空间。

main { 
  display: grid;
  grid-template-columns: 14ch repeat(auto-fill, minmax(28ch, 1fr)) 14ch;
  grid-template-rows: masonry;
  gap: 1rem;
}

这只是许许多多可能性中的一种。

CSS Grid 提供了大量用于定义网格轨道的选项,让你尽情发挥创造力:

  • 以任何单位定义的固定尺寸(px、em、rem、cqi、lh、ch、ic、cap、vw、svh 等)。
  • max-contentmin-content
  • 充分发挥 fr 单位的威力
  • minmax() 函数
  • %-sized
  • auto

有了 CSS Grid 中的这些选项,你就能以有趣的方式创建更加动态和灵活的内容。您可以创建两个阶段的灵活性,因为 fr 单位大小的列与 minmax()大小的列是在不同阶段增长和收缩的。max-contentmin-content 值可以根据内容大小来调整列的大小,而不是根据列的大小来调整内容的大小。fr 单位可以很容易地用于创建复合或不对称网格,即不同大小的列。选择是无限的。

通过在 CSS 网格中添加以砌体/瀑布模式包装内容的功能,我们可以保持网格的全部功能,以我们喜欢的方式定义列。

例如,让我们使用 grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr) 来创建窄列和宽列交替的模式,所有列都是灵活的。当有空间时,会添加更多的列。列数总是奇数,最后以窄列结束。

图4:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

即使我们只使用简单的 fr 单位定义列,CSS Grid 提供的强大功能也能将不同的列设置为不同的大小。为了好玩,让我们在 grid-template-columns 中使用 fr 单位来定义一组列的大小,通过使用斐波那契数列来注入黄金比例的活力:grid-template-columns: 1fr 1fr 2fr 3fr 5fr 8fr;

图5:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

举个更实际的例子,让我们在定义列时使用最大内容。基于内容的大小是 CSS 网格的一个非常强大的功能。本演示中的巨型菜单布局使用了 grid-template-columns: repeat(auto-fill, minmax(max-content, 30ch)); 来确保每一列都足够大,以容纳每一个链接,而不会包裹文本。

图6:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

巨型菜单一直很难编码,尤其是在多种屏幕尺寸下。有了 CSS Grid Level 3,这一切都变得异常简单。只需几行代码,就能创建一个动态布局,在空间允许的情况下一次添加或删除一列,无需任何媒体/容器查询,还能防止缠绕。

如果将masonry 作为一种单独的display类型,许多示例都无法创建。关于display: masonry的讨论是只允许对称列(彼此大小相同的列),这与现在的多列布局非常相似。

利用网格功能,让内容跨列显示

CSS 网格还能让我们在多列之间跨项。让我们利用这一功能,看看会出现哪些有趣的选项。让第 5 张图片跨两列网格,而其余图片只跨一列,这样如何?

图7:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

如果我们在宽高比更宽的图片上添加一个更宽的类,让这些图片跨越多列,效果会更好。我们还可以稍微改变一下样式,将四角变方而不是变圆,并将网格间隙减小为零。这样,我们就能以不同的方式将不同纵横比的照片打包在一起。

图8:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

 

我们还尝试将经典的砌体/瀑布式照片布局与视图转换相结合。当用户点击/轻敲任何照片时,它就会变大,横跨多列。浏览器会自动进行动画转换。(本演示需要 Safari 技术预览版 192 或更高版本)。

 

这些照片和巨型菜单演示的变体只是在列方向上充分利用 CSS 网格的全部功能,同时关闭行时所能实现的众多可能性的一小部分。

列式与模块化网格

如果我们不断尝试,会发生什么呢?让我们抛开 “masonry”的想法,开始将第 3 级网格纯粹想象成网格的扩展。CSS Grid Level 3 的核心是提供一种关闭行的机制。它让我们可以创建列式网格,即仅由列组成的网格。

相比之下,模块化网格是一种所有内容都按列和行排列的网格。这种网格在 20 世纪现代主义平面设计盛行时期开始流行。CSS Grid Level 1 擅长制作模块化网格……这正是它想要做的。事实上,基于浮动的布局也鼓励在网页上创建模块化网格,因为你必须让所有内容高度一致,才能让浮动清晰可见。图片的长宽比必须相同。文字的长度必须相同。这通常在后端通过内容管理系统强制执行的策略来实现,或者在前端通过 CSS 对内容进行截断/裁剪来实现。

对于网站来说,使用这种模块化网格是很常见的,这里使用的是 CSS 网格 1 级。

图9:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

 

当然,这个例子过于简单。文章前导看起来光秃秃的,没有预告图片。千篇一律的设计过于严格和正式,缺乏活力。真正的网站会找到其他方法为设计注入活力。

但是,如果布局本身也能带来一些活力和趣味呢?如果我们使用 CSS 网格来创建列式网格,就像创建模块化网格一样简单,会发生什么呢?如果我们不截断内容,而是让内容按照自己想要的大小排列,让布局为内容服务,而不是强迫内容为布局服务,又会怎样呢?

一个经典的砌体/瀑布式布局,配以不同长度的文字,看起来就像这样,这已经更吸引人了,因为用户可以阅读更多关于每篇文章的内容:

图10:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

 

不过,这在视觉上还是有点重复。对称的列式网格通常都是如此。我们需要利用 CSS 网格的其他功能来做一些更有趣的事情。让我们把最新的文章做得更大,让它横跨四列。其他几篇最新文章的大小适中,横跨两列。而较早的内容则较小,只占一列。

图11:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

 

现在,这些原本视觉枯燥的文字开始变得生动起来。如果我们在每篇文章中添加图片,就会使文章更加生动。

让我们在一个博物馆的网页上尝试将图片和文字混合在一起。第一个网格项是介绍博物馆的页眉,并提供其他资源的导航。其余内容包括艺术品及其信息:标题、艺术家、年份、媒介、目录编号和地点。

由于画作非常华丽,因此在经典的砌体/瀑布式布局中,内容看起来非常不错。

图12:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

 

让我们看看利用 CSS 网格的两个更强大的功能–子网格和显式放置,我们还能做些什么。

使用子网格和显式布局

CSS Grid Level 2 中的子网格功能非常强大,而且大多数浏览器最终都支持该功能。

让我们看看如何更好地利用可用空间,而不是在左对齐的一列中列出绘画的元数据。通过使用子网格,我们可以将年份和目录编号放在每张卡片的右侧,并将其中一幅画的数据与其他画的相同数据排成一行。

图13:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局

 

通过在 CSS Grid Level 3 中添加这一新功能,我们获得了现有开发工具的优势。您现在就可以在 Safari 技术预览版中使用网格检查器,试用 grid-template-rows: masonry

如果Masonry是自己的display类型,而不是 CSS 网格的一部分,那么它将无法获得子网格的好处。

我们还可以利用 CSS Grid Level 1 的强大功能,将页眉明确放置在最后两列中,并使用 grid-column 将其移动到页面右上角:grid-column: -3 / -1

 

只需几行布局代码,我们就能充分利用 CSS 网格级别 1、2 和 3 的强大功能,创建灵活的列,并根据可用尺寸改变列的数量,而无需使用任何媒体查询或容器查询。

希望你能看到将砌体/瀑布流布局机制与 CSS 网格充分结合的优势,它提供了比砌体布局更多的创造性可能性。

讨论

下面我们就来讨论一下阻碍 CSS 工作组继续前进的争论。我们希望网页设计师和开发人员能就 CSS 的发展方向发表自己的看法(在社交媒体上发表、撰写博文)。

有些人,包括我们苹果公司的人,喜欢将 “Masonry “作为 CSS 网格的一部分。我们认为,该功能是扩展 CSS 网格的一种机制,使其最终能够创建列式网格和模块化网格。我们希望这一功能能与网格的所有其他功能相结合,包括定义列、轨道跨度、显式放置和子网格等强大选项。

而其他人则认为 Masonry 应该是一种独立的display 类型。乍一看,用新的display 类型定义 Masonry 可能很有意义。布局类型之间的分隔确实很整齐。

display: block;
display: inline;
display: flexbox;
display: grid;
display: masonry;

CSS 工作组尚未讨论单独的Masonry display 类型的语法是如何工作的,但或许可以仿效多列布局。

main { 
  display: masonry;
  columns: 28ch;
}

或者,语法可以仿照 Grid,但有很大的局限性:

main {
  display: masonry;
  masonry-columns: repeat(5, minmax(28ch, 1fr)); 
                   /* where only one repeating width is allowed */
}

 

无论如何,该选项的支持者显然希望 Masonry 只限于对称网格,即所有列的大小相同。而 CSS 网格的其他轨迹大小功能都不允许使用。

将Masonry 作为一种简单而独立的布局类型,可以避免为保持网格和Masonry的协同工作而进行的必要工作,无论是现在还是将来。这样做可以简化布局模型,使其更容易在浏览器中实现,减少潜在的性能陷阱,并允许网格和Masonry的功能集分离。

相反,我们认为,为 CSS 网格添加这一功能所需的努力值得,因为它能带来很多好处。CSS 网格第 3 级规范已经编写完成,并已在两个浏览器引擎中实现。是的,虽然让 CSS 网格变得更加复杂会增加将来扩展的难度,但我们认为让这两种类型的网格布局相互交织在一起还是有好处的。这样,CSS 工作组将始终定义模块化网格和列式网格的所有新添加内容。这样就不会出现display: grid中添加的内容被display: masonry所遗漏的情况,反之亦然。例如,许多开发人员都希望 CSS Grid Level 4 能提供一种机制,用于对网格区域和网格线进行样式设置–或许是为轨道添加背景色的方法,或者是在间隙中创建规则线的方法。如果能从第一天起就确保模块化网格和列式网格都能使用这种机制,那就再好不过了。

display: masonry的支持者提出的另一个论点是,从概念上讲,砌体是一种与 CSS 网格根本不同的布局类型,因此应该有自己的display类型。他们经常将 CSS 网格描述为本质上是 “在二维空间中排列事物”,而砌体只在一维空间中排列事物,因此 “它不是网格”。(事实上,有些人认为砌筑更像 Flexbox,因为 “两者都是在一个方向上排列”)。

在很多方面,你对这个问题的看法可能取决于你对网格的想象。

什么是网格?

网格是平面设计中一个非常重要的方面。网格用于将文字、图像和其他内容以规则的模式排成一行。通过使事物具有可预测性,网格有助于提高可读性和可用性。

网格的使用可以追溯到几千年前。

图14:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局
[Left] Antoine Vérard published a French translation of Boccaccio in 1498. Seen in Thirty Centuries of Graphic Design, by James Craig and Bruce Barton, 1987. [Right] A Russian illustrated sheet proclaiming that ‘Hops are head above all other fruit’. Seen in Books: A Living History by Martyn Lyons, 2011.

 

直到 20 世纪,欧洲和美国的现代主义者才开始提倡 “正确的 “平面设计网格应该双向排列内容–行和列。

图15:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局
Massimo Vignelli is especially well-known for promoting the idea that lining things up in both columns and rows is a superior practice of graphic design. Two examples from The Vignelli Canon, 2010.

 

时至今日,关于哪种网格是最佳网格或唯一合法网格的争论仍不绝于耳。许多设计师声称,12 列网格是设计网页的唯一正确方法–或者 12 列用于 “桌面”,8 列用于 “平板电脑”,4 列用于 “手机”。有时,设计师们对 “正确的网格 “的理解变得相当虔诚。

马克-布尔顿(Mark Boulton)多年来一直认为,对称的柱状网格是非常公式化和无聊的。他提倡在网页设计中使用非对称复合网格。如今,幸运的是,CSS Grid Level 1 让创建非对称网格和复合网格变得异常简单,设计师可以自由地创建他们想要的网格。但前提是,他们还希望所有网格都是模块化网格。

事实上,模块化网格和列式网格都是网格。CSS 网格理应也能创建柱状网格。

图16:【外评】请帮助我们实现 CSS grid 布局 Level 3,又称“砌体 Masonry”布局
Ideas for designing columnar grids, in Editing by Design, by Jan V. White.

 

我们相信,CSS 有机会让丰富的设计网格出现在网络上,如果新的砌体功能仅限于对称的柱状网格,我们将深感失望。

您怎么看?

我们想听听您的意见

这就是您的参与之处。尝试一些您自己的演示。在自己的博客上写下你的想法。在本期的 CSS 工作组中发表评论

  • “masonry”/“waterfall” 是否应该成为 CSS 网格的一部分?
  • 你是否想要通过 CSS Grid 定义列式网格的功能–使用子网格、跨度、显式放置,以及所有关于轨迹大小的选项?还是说,你只想获得定义大小相等列的经典Masonry布局的功能?
  • 你会使用它吗?你可以用它创建什么?
  • 您有自己制作的演示链接吗?我们希望了解您的想法和使用案例。
  • 你想做的事情中是否有这个模型做不到的?

通常情况下,理论上的思考和实际使用中的体验是截然不同的。为了确保 CSSWG 能够正确地设计这一功能,我们需要开发人员获得一些实际经验,并将你们的想法表达出来。

WebKit 团队开发 Masonry 已经有一年半的时间。2023 年 2 月,它首次在 Safari 技术预览版 163 中默认启用。我们还需要进一步打磨,并解决一些细节问题(命名就是其中之一)。但我们希望尽快推出这一功能。为此,我们需要解决这些基本问题。

感谢您的帮助!

附注:关于名称…

对于这个新值来说,”masonry  “很可能不是最好的名字。CSS 中的名称通常是直接描述其创建结果的简单单词,如centerundercontaincliprevertltralwaysbreak-wordhiddenallow-endscale-downwrapsmooth

而 “masonry  “这个词更像是一个隐喻,需要用背景故事来解释其含义。对于不懂英语的开发人员来说,这样的术语更难记忆。可以说,语法可以很容易地用 grid-template-rows: waterfall 来代替,因为这是某些地区使用的这种布局的主要术语,而不是Masonry结构。

此外,一旦你开始编写大量使用该功能的代码,你很可能就会像我们一样意识到:这与 Pinterest 或其他类似网站使用的布局无关。这是一种告诉浏览器 “请创建一个网格,但不要有任何行 “的机制。

也许最好的语法是 grid-template-rows: none; 来表达 “请不要给我任何行”。遗憾的是,现在使用这个名称为时已晚,因为 nonegrid-template-* 的默认值,表示 “请只给我隐式行,不给我显式行”。

相反,我们可以使用 off 来表达 “请关闭行方向的网格,只给我列 “的意思。

main { 
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(14rem, 1fr));
  grid-template-rows: off; 
}

 

CSSWG 正在本期讨论这个名称。如果您对名称有想法或偏好,请参与讨论。

同时,”masonry  “是目前在 Safari 技术预览版中实现的值,因为这是编辑器草案目前使用的值。因此,这就是我们在上述演示中使用的值,你也应该在你的演示中使用它。但请注意,这个值的名称将来会有变化。也许将来我们会将其称为 “columnar grid “或 “Grid Level 3″,而不是 “Masonry”。

本文文字及图片出自 Help us invent CSS Grid Level 3, aka “Masonry” layout

你也许感兴趣的:

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注