需要反馈:我们应如何定义 CSS 砌体?

Ian Kilpatrick
Ian Kilpatrick
Tab Atkins-Bittner
Tab Atkins-Bittner

发布时间:2024 年 9 月 19 日

CSS 工作组已将这两个 CSS 图块排列方案合并为一份草稿规范。该团队希望这样做有助于您更轻松地比较这两种方案,并做出最终决定。Chrome 团队仍认为,采用单独的图块砌体语法是最佳方式。虽然我们之前的文章中提到的最大性能问题已得到解决,但我们仍对语法、初始值以及与网格结合使用时版本的易学性存有疑虑。

不过,为了验证我们的假设,我们通过一些示例来展示了每种版本的砌体效果。请查看本文中的示例,并向我们提供反馈,以便我们做出决定并继续推出此功能。

本文并未涵盖所有可能的用例,但很明显,将砖块砌图与网格布局分离不会导致该功能缺少功能。事实上,情况可能恰恰相反。正如您将在本文中看到的,display: masonry 版本提供了新的机会和更简单的语法。此外,许多开发者都担心,使用砖块排列方式重新排列项可能会导致无障碍问题。我们还通过建议的 reading-flow 属性解决了这个问题,使这两种语法版本都适用。

基本图块砌布局

这是大多数人想到砖石砌图时会想象到的布局。项会以行显示,第一行放置后,后续项会移至较短项留下的空间。

包含列的布局,填充列的项之间没有间隔。
在此布局中,系统会先定义列,然后按砖石砌图案(而非严格按行)填充项。

活动门票提供商:display: masonry

如需创建砖块砌图布局,请为 display 属性使用值 masonry。这会创建一个砖块布局,其中包含您定义(或由内容定义)的列轨道,以及另一个轴中的砖块。第一个项显示在块级和内嵌起始位置(因此在英语中是左上角),并且项采用内嵌方向排列。

如需定义曲目,请将 masonry-template-tracks 与 CSS 网格布局中使用的曲目列表值搭配使用。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(3, 1fr);
  gap: 10px;
}

活动门票提供商:display: grid

如需创建砖块布局,请先使用 display 属性的值 grid 创建网格布局。使用 grid-template-columns 属性定义列,然后将 grid-template-rows 的值设为 masonry

这将创建一个与自动放置的网格项预期相同的布局,不过,每行中的项使用的是砖块布局,并会重新排列以占用前一行较小项留下的空间。

.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;
  gap: 10px;
}

在两种方案之间做出选择时应考虑的事项

这两种方法之间的一个显著区别是,使用 display: masonry 版本时,即使您未使用 masonry-template-tracks 指定任何轨道,也会获得砖块砌布局。因此,您可能只需要 display: masonry。这是因为 masonry-template-tracks 的初始值为 repeat(auto-areas, auto)。布局会根据容器的大小创建尽可能多的自动大小轨道。

使用砖石的反向流

规范中包含更改图块流方向的方法。例如,您可以更改流程,以便从块末尾开始显示。

包含列的布局,填充列的项从布局底部开始。
在此布局中,首先定义列,然后从块末尾开始按砖石砌图案填充项。

活动门票提供商:display: masonry

使用 display: masonry 创建砖块砌图布局,然后使用值为 column-reversemasonry-direction

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(3, 1fr);
  masonry-direction: column-reverse;
}

活动门票提供商:display: grid

使用 display: gridgrid-template-rows: masonry 创建砖块布局。 然后,使用 grid-auto-flow 属性(新值为 row-reverse)使项从网格容器的块端进行布局。

.masonry {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: masonry;
  grid-auto-flow: row-reverse;
}

在两种方案之间做出选择时应考虑的事项

display: masonry 版本的运作方式与 flexbox 非常相似。使用值为 column-reversemasonry-direction 属性更改列的流向。

CSS 网格版本使用 grid-auto-flow。按照目前的定义,grid-auto-flow: row-reversegrid-auto-flow: column-reverse 会产生相同的效果。这可能会令人困惑,因为您可能希望它们执行其他操作。

行砖石砌

您还可以更改方向来定义行。

包含行的一项布局,填充行的内容之间没有间隔。
在此布局中,系统会先定义行,然后按砖石砌图案(而非严格的列)填充项。

活动门票提供商:display: masonry

使用 display: masonry 创建砖块砌图布局,然后将 masonry-direction 的值设置为 row。除非您希望行具有特定的块大小,否则无需指定任何轨道大小,因为默认值为 auto,因此轨道将根据其包含的内容调整大小。

.masonry {
  display: masonry;
  masonry-direction: row;
}

活动门票提供商:display: grid

.masonry {
  display: grid;
  grid-template-columns: masonry;
  grid-template-rows: repeat(3, 1fr);
}

在两种方案之间做出选择时应考虑的事项

与反向流程一样,将 display: masonry 版本从列更改为行,意味着更改 masonry-direction 的值。对于网格版本,您需要切换 grid-template-columnsgrid-template-rows 属性的值。或者,如果使用缩写,请更改语法的顺序。

在这两个切换流程示例中,display: masonry 版本看起来更直观。只有一个属性用于控制流程 masonry-direction,它采用以下值之一:

  • row
  • column
  • row-reverse
  • column-reverse

然后,假设默认的“auto”值不符合您的需求,您可以向 masonry-template-tracks 添加所需的任何尺寸信息。

对于网格,如需实现反向方向,您需要使用 grid-auto-flow 属性;如需实现行图块模式,请切换 grid-template-* 属性的值。此外,在当前网格语法中,也无法将网格轴的值留为未定义。您始终需要在值不为 masonry 的轴上指定 grid-template-* 属性。

排列项

在这两个版本中,您都可以使用熟悉的基于行的放置方式来明确放置项。在这两个版本中,您只能在网格轴(即具有预定义轨道的轴)中定位项,而不能在采用砖块布局的轴上定位项。

活动门票提供商:display: masonry

以下 CSS 定义了一个包含四列的图块砌体布局。因此,网格轴是列。类为 a 的项从第一列行放置到第三列行,跨越两个轨道,并具有新的 masonry-track-* 属性。这也可以定义为 masonry-track: 1 / 3; 的简写形式。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(4, 1fr);
}

.a {
  masonry-track-start: 1;
  masonry-track-end: 3;
}

活动门票提供商:display: grid

以下 CSS 定义了一个包含四列的图块砌体布局。因此,网格轴是列。类为 a 的项从第一列行放置到第三列行,跨越具有 grid-column-* 属性的两个轨道。这也可以定义为 grid-column: 1 / 3; 的简写形式。

如果网格轴是列,则系统会忽略 grid-row-* 属性;如果网格轴是行,则系统会忽略 grid-columns-* 属性。

.masonry {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: masonry;
}

.a {
  grid-column-start: 1;
  grid-column-end: 3;
}

您可以将命名行与这两种语法搭配使用。以下示例展示了一个网格,其中包含两个名为 a 的列线。

活动门票提供商:display: masonry

命名行在 masonry-template-tracks 的曲目列表值中定义。该项可放置在名为 a 的任何行之后。

.masonry {
  display: masonry;
  masonry-template-tracks: 100px [a] auto [a] auto 100px;
}

.item {
  masonry-track: a;
}

活动门票提供商:display: grid

命名行在 grid-template-columns 的曲目列表值中定义。该项位于名为 a 的第一行后面。如果定义了 grid-row 属性,系统会忽略该属性。

.masonry {
  display: grid;
  grid-template-columns: 100px [a] auto [a] auto 100px;
  grid-template-rows: masonry;
}

.item {
  grid-column: a;
  grid-row: a; /* ignored */
}

您还可以在这两种语法中使用命名区域。以下示例展示了一个网格,其中包含三个名为“a”“b”和“c”的轨道。

活动门票提供商:display: masonry

轨道的命名方式为 masonry-template-areas 的值。由于未定义轨道大小,因此所有三个轨道均默认为 auto 大小。该项会放置在“a”轨道中。

.masonry {
  display: masonry;
  masonry-template-areas: "a b c";
}

.item {
  masonry-track: a;
}

无论您是定义行还是列,此方法都适用;唯一的区别在于 masonry-direction 属性。

活动门票提供商:display: grid

对于,语法基本相同。同样,由于未定义任何轨道大小,因此所有三个轨道都默认为 auto 大小,但您仍然需要明确说明另一个轴是砖块模式:

.masonry {
  display: grid;
  grid-template-areas: "a b c";
  grid-template-rows: masonry;
}

.item {
  grid-column: a;
}

不过,对于,值的写法必须有所不同,因为 grid-template-areas 实际上是在定义一个二维区域,并且每行都写为一个单独的字符串:

.masonry {
  display: grid;
  grid-template-areas: "a" "b" "c"; /* Note the difference, each row is quoted. */
  grid-template-columns: masonry;
}

.item {
  grid-row: a;
}

在两种方案之间做出选择时应考虑的事项

无论采用何种定位,在切换方向时,display: masonry 语法都更适用。由于 masonry-track-* 属性适用于网格轴的任意方向,因此您只需更改 masonry-direction 的值即可更改方向。对于网格版,您至少需要冗余的房源才能实现切换。不过,请参阅前面的示例,了解在网格版本中更改方向的其他更复杂的方式。

简写

在本文中,我们使用了长格式,以更清楚地说明使用的是哪些属性,不过您也可以使用缩写形式来定义 display: masonrydisplay: grid 版本。

活动门票提供商:display: masonry

display: masonry 缩写使用 masonry 关键字。如需创建基本图块砌布局,请使用以下 CSS:

.masonry {
  display: masonry;
  masonry: repeat(3, 1fr);
}

如需创建简单的行式图块布局,请执行以下操作:

.masonry {
  display: masonry;
  masonry: row;
}

如需使用缩写定义轨道和基于行的布局,请执行以下操作:

.masonry {
  display: masonry;
  masonry: repeat(3, 1fr) row;
}

活动门票提供商:display: grid

使用 grid 缩写创建基本图块砌体布局。

.masonry {
  display: grid;
  grid: masonry / repeat(3, 1fr);
}

如需创建简单的行式图块布局,请执行以下操作:

.masonry {
  display: grid;
  grid: repeat(3, auto) / masonry;
}

在更复杂的示例中,由于整体 display:masonry 语法更简单,因此可以将更多属性打包到缩写中,而不会使其过于复杂。

例如,假设您创建了三个列,分别命名为“a”“b”和“c”,并从下往上填充。

活动门票提供商:display:masonry

display: masonry 中,可以使用缩写形式同时设置这三个值:

.masonry {
  display: masonry;
  masonry: column-reverse "a b c";
}

由于这些图片会自动调整大小,因此您无需指定尺寸,但如果您想使用特定尺寸,也可以添加。例如:masonry: column-reverse 50px 100px 200px "a b c";

此外,每个组件都可以自由重新排序;您无需记住任何特定顺序。如果您想改为处理行,只需将 column-reverse 替换为 rowrow-reverse;其余语法保持不变。

活动门票提供商:display: grid

display: grid 中,必须单独设置这三个方面:

.masonry {
  display: grid;
  grid-template-rows: masonry;
  grid-template-areas: "a b c";
  grid-auto-flow: wrap-reverse;
}

与砖块砌图案示例一样,这会使所有列的大小均为 auto,但如果您想提供明确的大小,可以执行以下操作:

.masonry {
  display: grid;
  grid: masonry / 50px 100px 200px;
  grid-template-areas: "a b c";
  grid-auto-flow: wrap-reverse;
}

或者,如果您想使用“网格”同时设置尺寸和区域名称,请执行以下操作:

.masonry {
  display: grid;
  grid: "a b c" masonry / 50px 100px 200px;
  grid-auto-flow: wrap-reverse;
}

在这两个示例中,顺序是严格要求的,如果您想使用行,则顺序会有所不同。例如,更改为行后,结果如下所示:

.masonry {
  display: grid;
  grid: 50px 100px 200px / masonry;
  grid-template-areas: "a" "b" "c";
}

或者,将所有这些都简写为:

.masonry {
  display: grid;
  grid: "a" 50px "b" 100px "c"  200px / masonry;
}

在两种方案之间做出选择时应考虑的事项

由于 display: masonry 是相对简单的缩写,因此可能会被广泛使用。在许多情况下,对于“标准”图块砌布局,您只需设置轨道定义;所有其他值都可以采用默认值。

display: grid 版本使用现有的 grid 简写形式,这是一种相当复杂的简写形式,据我们的经验,开发者使用这种简写形式的频率较低。如前面的示例所示,即使用于简单的砖块砌图布局,在设置值的顺序时也需要小心谨慎。

其他注意事项

本文介绍了目前一些常见的使用场景,但我们尚不清楚网格或砖块布局的未来发展趋势。使用单独的 display: masonry 语法的一大理由是,这允许这两者在未来分道扬镳。特别是对于初始值(例如 masonry-template-tracks 的值),在砖块砌图中执行与网格不同的操作可能很有用。如果使用 display: grid 版本,我们将无法更改网格的默认值,这可能会限制我们日后想要执行的操作。

在这些示例中,您可以看到在使用砖块砌图时,浏览器必须忽略在网格中有效的属性。例如 grid-template-areas,其中大多数值都会被舍弃,因为它定义了二维网格布局,而在砖块砌图中,我们只会完全定义一个方向。

提供反馈

请查看这些示例,以及将每个版本并排展示的规范草稿。请通过对问题 9041 发表评论告诉我们您的想法。如果您更喜欢在自己的博客或社交媒体上撰写帖子,请务必在 XLinkedIn 上告诉我们。