CSS 磚石的替代提案

Chrome 團隊很樂意在網路上實作砌磚式版面配置。不過,我們認為將其納入 CSS 格線規格,如最近的 WebKit 文章所提議,是錯誤的做法。我們也認為,WebKit 的文章反對的版本並非沒有人提出的 masonry 版本。

因此,這篇文章旨在說明 Chrome 為何擔心在 CSS 格線版面配置規格中實作疊砌,並明確說明替代提案可提供哪些功能。簡單來說,

  • Chrome 團隊非常希望解除平鋪的封鎖,因為我們知道這是開發人員想要的功能。
  • 除了您是否認為平鋪排版是格線之外,將平鋪排版新增至格線規格也可能會發生問題。
  • 在格線規格之外定義平鋪排列,並不會防止平鋪排列使用多個軌道大小、使用對齊或間距等屬性,或使用格線版面配置中的任何其他功能。

是否應將平鋪排版納入格狀排版?

Chrome 團隊認為,磚牆排版應為獨立的版面配置方法,使用 display: masonry 定義 (或其他關鍵字,如果有更好的名稱,請決定使用哪一個)。在本文稍後的部分,您可以看到程式碼中可能會是什麼樣子的範例。

我們認為,在格狀版面配置之外定義平鋪版面配置會比較適合,原因有兩個:可能發生的版面配置效能問題,以及平鋪版面配置和格狀版面配置都具有某種版面配置方法的功能,但另一種方法則沒有。

成效

就瀏覽器處理大小和位置的方式而言,格狀和馬賽克的做法是相反的。格線排版時,所有項目都會放在版面配置之前,瀏覽器會確切知道每個軌道的內容。這可讓您在格狀中使用複雜的內在大小設定。使用磚塊排版時,項目會依照排版方式放置,瀏覽器不會知道每個軌道有多少項目。這並非所有內在大小或固定大小的音軌都會發生的問題,但如果混合固定和內在音軌,就會發生這種問題。為瞭解決這個問題,瀏覽器需要執行預先版面配置步驟,以盡可能的方式排版每個項目,以便取得測量值,但大型格線會導致版面配置效能問題。

因此,如果您使用了採用 grid-template-columns: 200px auto 200px 的軌跡定義的平鋪版面配置 (這是在格狀版面配置中常見的做法),就會開始遇到問題。一旦新增子格線,這些問題就會以指數方式增加

有人認為大多數使用者不會遇到這個問題,但我們已經知道使用者確實會使用非常大的格線。我們不希望在有其他方法可用時,推出使用方式受限的產品。

我們該如何處理在各版面配置方法中不合理的內容?

當彈性容器和格線成為 CSS 的一部分時,開發人員經常覺得這兩者會以不一致的方式運作。他們遇到的內容不一致問題,是因為長期以來對區塊版面配置的假設,對版面配置運作方式有錯誤認知。隨著時間推移,開發人員開始瞭解格式設定內容。當我們切換至格線或 Flex 格式設定時,某些項目的行為會有所不同。舉例來說,您知道在彈性容器中,並非所有對齊方法都適用,因為彈性容器是單維度。

將平鋪排版整合至格線,會中斷格式化內容與對齊屬性等可用性之間的明確連結,這些屬性是在每個格式化內容的「Box Alignment」規格中定義。

如果我們決定透過在平鋪中將混合內在和固定軌跡定義設為非法,來處理先前提到的效能問題,請務必記住,適用於格線版面的非常常見模式不適用於平鋪。

在砌磚模式中,有些模式也相當實用,例如 grid-template-columns: repeat(auto-fill, max-content),因為您沒有交叉限制,但需要在格狀中保持無效。以下是我們預期會產生不同行為或具有不同有效值的屬性清單。

  • grid-template-areas:在平鋪排版中,您只能在非平鋪排方向中指定初始資料列。
  • grid-template:縮寫字串必須考量所有差異。
  • 由於合法值不同,請追蹤 grid-template-columnsgrid-template-rows 的大小值。
  • grid-auto-flow 不適用於平鋪,masonry-auto-flow 不適用於格狀。合併這些元素會導致問題,因為您使用的版面配置方法會導致這些元素無效。
  • 格狀有四個刊登位置屬性 (grid-column-start 等),而平鋪只有兩個。
  • Grid 可使用所有 justify-*align-* 屬性,但 Masonry 只使用 flexbox 等子集。

您也必須指定,如果開發人員使用在「含有磚塊排版」或「不含磚塊排版」的格狀布局中無效的值,會發生什麼情況。舉例來說,您可以使用 grid-template-columns: masonrygrid-template-rows: masonry,但不能同時使用兩者。如果同時使用這兩種方法,會發生什麼情況?您必須指定這些詳細資料,才能讓所有瀏覽器執行相同的操作。

無論現在或未來,從規格角度來看,這一切都變得複雜。我們需要確保所有內容都考量到馬賽克排版,並且在馬賽克排版中運作。這對開發人員來說也令人困惑。為什麼您需要記住,即使使用 display: grid,某些功能還是無法運作,因為使用了馬賽克排版?

其他提案

如前所述,Chrome 團隊希望在格狀規格之外定義平鋪排版。這並不表示只能使用簡單的版面配置方法,且欄大小必須相同。WebKit 文章中的所有示範仍可行。

傳統磚牆版面配置

大多數人想到的平鋪排版,是指包含多個等大欄的版面配置。這會使用下列 CSS 定義,比起相等的網格內含版本,這需要的程式碼行數會減少一行。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(14rem, 1fr));
  gap: 1rem;
}

大小相等的音軌。

使用格線類型軌道大小來設定不同的欄寬

除了先前提到的內在和固定軌道大小混合問題外,您可以使用格線中的所有軌道大小。例如 WebKit 網誌文章中的範例,這是一種重複的窄欄和寬欄模式。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, minmax(8rem, 1fr) minmax(16rem, 2fr)) minmax(8rem, 1fr);
  gap: 1rem;
}

寬窄交錯的軌道圖案。

適用於平鋪式排版的其他軌道大小

由於格狀是二維版面配置方法,因此我們不允許在格狀中使用其他音軌大小選項。這些元素在疊砌排版中很實用,但如果在格狀排版中無法運作,就會造成混淆。

自動填入 max-content 大小的音軌。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, max-content);
  gap: 1rem;
}

自動填入 auto 大小的音軌,系統會建立相同大小的音軌,並自動調整大小以容納最大的音軌。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
  gap: 1rem;
}

使用自動調整大小的軌道進行 Masonry 排版。

允許內容橫跨欄位,並將項目放在疊放版面配置上

在個別的平鋪規格中,內容跨越欄位並無不妥。這可能會使用 masonry-track 屬性,做為 masonry-track-startmasonry-track-end 的簡寫,因為在磚牆式版面配置中,您只有一個維度可跨越各項內容。

.masonry {
  display: masonry;
  masonry-template-tracks: repeat(auto-fill, auto);
}

.span-2 {
  masonry-track: span 2; /* spans two columns */
}

.placed {
  masonry-track: 2 / 5; /* covers tracks 2, 3, and 4 */
}

使用已放置和跨越項目的 Masonry 樣式。

採用磚牆式軌道的子磚牆或子格線

這項功能可透過獨立的砌磚規格支援,但仍須遵守條件,即不允許混合內在和固定大小的軌道。您必須明確定義該內容的確切外觀。我們認為這不會有任何問題。

結論

我們希望能達到可提供互通性的規格。不過,我們希望以現在和未來都能正常運作的方式進行,並且能讓開發人員信賴。要解決上述效能問題,唯一的方法就是讓第二個問題 (即在平鋪排版中使用非法格線) 變得更嚴重。我們認為這並非理想的解決方案,尤其是在您可以使用所有所需的格線功能,同時保持不同項目的明確區隔時。

如有任何意見回饋,請加入Issue 9041 的討論。

感謝 Bramus、Tab Atkins-Bittner、Una Kravets、Ian Kilpatrick 和 Chris Harrelson 審查這篇文章,以及提供相關討論內容。