需要意見回饋:我們應該如何定義 CSS 馬賽克?

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

發布日期:2024 年 9 月 19 日

CSS 工作小組已將兩個 CSS 砌磚提案合併為一項草擬規格。這個小組希望這麼做,讓您更容易比較兩者並做出最終決定。Chrome 團隊仍認為,使用獨立的馬賽克語法是最佳做法。雖然上一篇文章提到的最大效能問題已解決,但仍有幾個疑慮,包括語法、初始值,以及結合格線的版本是否容易上手。

不過,為了驗證我們的假設,我們已透過一些範例說明 Masonry 如何與各個版本搭配運作。請參考本文提供的範例,並提供意見回饋,以便我們做出決定並繼續推出這項功能。

本篇文章未涵蓋所有可能的用途,但很明顯的是,將馬賽克圖案與格狀版面配置分開,不會導致這項功能缺乏功能。事實上,反之亦然。如這篇文章所述,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)。版面配置會建立盡可能多且符合容器大小的自動大小音軌。

使用 masonry 的反向流程

規格中包含變更砌磚流程方向的方法。舉例來說,您可以從區塊結尾處變更要顯示的流程。

版面配置有欄,填入欄位的項目會從版面配置的底部開始。
在這個版面配置中,系統會定義欄,然後從區塊結尾開始,以砌磚方式填入項目。

前往 display: masonry

使用 display: masonry 建立疊放版面配置,然後使用 masonry-directioncolumn-reverse 值。

.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 版本的運作方式與彈性容器非常相似。使用 masonry-direction 屬性 (值為 column-reverse) 變更資料欄的流向。

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

接著,您可以將需要的任何大小資訊新增至 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-reverserowrow-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 會將大部分的值捨棄,因為它定義了二維格狀版面配置,而我們在疊砌中只會完整定義一個方向。

提供意見回饋

請參閱這些範例,以及規格草稿,其中會將各個版本並列。歡迎在 Issue 9041 留言,告訴我們你的想法。如果想在自己的網誌或社群媒體上撰寫文章,請務必在 XLinkedIn 上告訴我們。