何時以及如何使用 CSS 多列佈局

已發表: 2022-03-10
快速總結↬當我們使用 Grid 和 Flexbox 時,多列佈局規範經常被忽視。 在這篇文章中,Rachel Andrew 解釋了為什麼它與其他佈局方法不同,並展示了一些有用的模式和站點來很好地展示它。

在所有關於 CSS 網格佈局和 Flexbox 的興奮中,另一種佈局方法經常被忽視。 在本文中,我將了解多列佈局——通常稱為多列或有時稱為“CSS 列”。 您會發現它適合哪些任務,以及製作專欄時需要注意的一些事項。

什麼是多列?

multicol 的基本思想是,您可以獲取大量內容並將其流入多個列中,就像在報紙中一樣。 您可以使用兩個屬性之一來執行此操作。 column-count屬性指定您希望內容分成的列數。 column-width屬性指定了理想的寬度,讓瀏覽器確定可以容納多少列。

將內容中的哪些元素變成多列容器並不重要,一切都保持正常流程,但分為列。 這使得 multicol 不同於我們今天在瀏覽器中使用的其他佈局方法。 例如,Flexbox 和 Grid,獲取容器的子元素,然後這些項目參與 flex 或網格佈局。 使用 multicol,除了在列內,您仍然可以正常流動。

在下面的示例中,我使用column-width來顯示至少14em的列。 Multicol 分配盡可能多14em列,然後在列之間共享剩餘空間。 列將至少為14em ,除非我們只能顯示一列,在這種情況下它可能會更小。 Multicol 是我們第一次在 CSS 中看到這種行為,默認情況下創建的列本質上是響應式的。 您不需要添加媒體查詢並更改各種斷點的列數,而是我們指定一個最佳寬度,瀏覽器會解決它。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:column-width。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:column-width。
跳躍後更多! 繼續往下看↓

樣式列

無法定位使用某一列屬性時創建的列框。 您無法使用 JavaScript 解決它們,也無法為單個框設置樣式以賦予其背景顏色或調整填充和邊距。 所有列框的大小都相同。 您唯一能做的就是在列之間添加一條規則,使用 column-rule 屬性,它的作用類似於邊框。 您還可以使用column-gap屬性控制列之間的間隙,該屬性的默認值為1em ,但是您可以將其更改為任何有效的長度單位。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:列樣式。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:列樣式。

這就是 multicol 的基本功能。 您可以獲取一大塊內容並將其拆分為列。 內容將依次填充列,沿內聯方向創建列。 您可以控制列之間的間隙並添加規則,其可能值與邊框相同。 到目前為止一切都很好,以上所有內容都在瀏覽器中得到了很好的支持,並且已經存在很長時間了,這使得這個規範在向後兼容性方面非常安全。

您可能還需要對您的欄目進行進一步考慮,以及在網絡上使用欄目時需要注意的一些潛在問題。

跨越列

有時您可能希望將某些內容分成列,然後使一個元素跨越列框。 將column-span屬性應用於 multicol 容器的後代可以實現這一點。

在下面的示例中,我使<blockquote>元素跨越我的列。 請注意,執行此操作時,內容會在 span 上方分成一組框,然後在下方開始一組新的列框。 內容不會跳過跨越的元素。

column-span屬性目前正在 Firefox 中實現,並且位於功能標誌後面。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:column-span。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:column-span。

請注意,在當前規範中, column-span的值為allnone 。 您不能只跨越某些列,但您可以通過將 multicol 與其他佈局方法相結合來獲得您可能在報紙上看到的那種佈局。 在下一個示例中,我有一個帶有兩個列軌道的網格容器。 左側軌道是2fr ,右側軌道是1fr 。 左側軌道中的文章我已經變成了一個帶有兩個軌道的多列容器,它還有一個跨越元素。

在右邊,我們有一個側面進入第二個網格列軌道。 通過嘗試我們可用的各種佈局方法,我們可以準確地確定哪種佈局方法適合手頭的工作——不要害怕混搭!

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Smashing Multicol:混合佈局方法。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Smashing Multicol:混合佈局方法。

控制內容中斷

如果您的內容包含標題,那麼您可能希望避免標題作為列中的最後一件事而內容進入下一列的情況。 如果您有帶有標題的圖像,那麼理想的情況是圖像和標題保持為一個單元,而不是跨列拆分。 為了解決這些問題,CSS 具有控制內容中斷位置的屬性。

當您將內容拆分為列時,您執行的是所謂的碎片化。 如果在頁面之間拆分內容也是如此,例如在為打印上下文創建樣式表時。 因此,與網頁上的其他佈局方法相比,multicol 最接近 Paged Media。 正因為如此,多年來控制內容中斷的方法一直是使用 CSS2.1 中的page-break-屬性。

  • page-break-before
  • page-break-after
  • page-break-inside

最近,CSS Fragmentation 規範定義了為任何碎片上下文設計的碎片屬性,該規範包括 Paged Media、multicol 和停滯區域規範的詳細信息; 區域也會分割一段連續的內容。 通過使這些屬性具有通用性,它們可以應用於任何未來的碎片化上下文,就像將 Flexbox 中的對齊屬性移到 Box Alignment 規範中一樣,以便它們可以在網格和塊佈局中使用。

  • break-before
  • break-after
  • break-inside

例如,我在<figure>元素上使用了break-inside avoid ,以防止標題與圖像分離。 支持的瀏覽器應該將圖形保持在一起,即使這會導致列看起來不平衡。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:break-inside。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:break-inside。

不幸的是,在 multicol 中對這些屬性的支持非常不完整。 即使在受支持的情況下,它們也應該被視為一種建議,因為在嘗試控制中斷時可能會發出如此多的請求,實際上瀏覽器實際上無法在任何地方中斷。 在這種情況下,規範確實定義了優先級,但是僅控制最重要的情況可能對您更有用。

網絡上的列問題

我們在網絡上沒有看到 multicol 被大量使用的一個原因是這樣一個事實,即很容易獲得一種讓讀者在塊維度中滾動的閱讀體驗。 對於我們這些使用英語或其他垂直書寫模式的人來說,這意味著垂直上下滾動。 這不是一個好的閱讀體驗!

如果您固定容器的高度,例如使用視口單元vh ,並且內容過多,則內聯方向會發生溢出,因此您會得到一個水平滾動條。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:溢出列。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Smashing Multicol:溢出列。

這些東西都不是理想的,在網絡上使用 multicol 是我們需要非常仔細地考慮我們可能打算流入我們的列的內容量的事情。

塊溢出列

對於規範的第 2 級,我們正在考慮如何啟用一種方法,通過該方法,當前最終導致水平滾動條的溢出列可以在塊方向上創建。 這意味著您可以擁有一個具有高度的多列容器,並且一旦內容創建了填充該容器的列,就會在下面創建一組新的列。 這看起來有點像我們上面的跨越示例,但是,不是有一個扳手導致新的列框開始,而是由一個在塊維度上有限制的容器引起的溢出。

此功能將使 multicol 對網絡更加有用。 雖然我們現在還有一點路要走,但您可以關注 CSS 工作組 repo 中的問題。 如果您有此功能的其他用例,請發布它們,它在設計新功能時真的很有幫助。

Multicol 對今天有什麼用?

根據當前規範,不建議將所有內容分成列而不考慮滾動問題。 但是,在某些情況下,multicol 在網絡上是理想的。 在查看設計模式時,有足夠多的用例使其成為您應該考慮的事情。

折疊小型 UI 或文本元素

Multicol 在您想要佔用較少空間的小項目列表的任何地方都很有用。 例如簡單的複選框列表或名稱列表。 通常在這些情況下,訪問者不會閱讀一列然後返回到下一列的頂部,而是掃描內容以查找要單擊的複選框或要選擇的項目。 即使您確實創建了滾動體驗,也可能不是問題。

您可以在 DonarMuseum 網站上看到 Sander de Jong 以這種方式使用的 multicol 示例。

名稱在 DonarMuseum 網站上排列成多個列
在 DonarMuseum 上,我們可以看到 multicol 用於顯示名稱列表。 (圖片來源)(大預覽)

已知的少量內容

有時我們在設計一個網站時,我們知道某些內容相對較小,並且適合大多數屏幕而不會導致不必要的滾動。 我在 Notist 演示頁面上使用了 multicol,作為演講的介紹。

Andy Clarke 為 Equfund 網站設計了一個可愛的例子。

包含各種內容的兩列佈局
在 Equfund 網站上,您可以看到不同的 HTML 元素在列內顯示時如何保持正常流動。 (圖片來源)(大預覽)

為了避免非常小的屏幕導致滾動的可能性,請記住您可以使用媒體查詢來檢查高度和寬度(或者在邏輯世界中,塊和內聯)。 如果您只在一個斷點啟用列,該斷點的min-height足以容納其內容,這可以節省滾動體驗很差的非常小的設備的用戶。

砌體式的內容顯示

多列佈局可以很好地工作的另一個地方是,如果你想創建一個砌體類型的內容顯示。 Multicol 是目前唯一可以創建這種高度不等的佈局的佈局方法。 網格要么留下空隙,要么拉伸項目以形成嚴格的二維網格。

Veerle Pieters 在她的靈感頁面上有一個以這種方式使用 multicol 的漂亮例子。

由 Veerle Pieters 設計的列中多個盒子的排列
在 Veerle Pieters 的這個設計中,multicol 用於將多個框或卡片佈局為列。 (大預覽)

Grid 和 Flexbox 後備

column-屬性也可以用作 Grid 和 Flex 佈局的後備。 如果您在容器上指定其中一個屬性,則使用display: flexdisplay: grid將該容器轉換為 Flex 或 Grid 佈局,任何列行為都將被刪除。 例如,如果您有一個使用網格佈局的卡片佈局,並且佈局在列中而不是跨頁面運行時將是可讀的,您可以使用 multicol 作為簡單的後備。 不支持 Grid 的瀏覽器會得到多列顯示,支持 Grid 的瀏覽器會得到 Grid Layout。

不要忘記多列!

我經常回答 Grid 和 Flexbox 問題,答案是不使用 Grid 或 Flexbox,而是使用 Multicol。 您可能不會在每個站點上都使用它,但是當您遇到用例時,它會很有幫助。 在 MDN 上,有很多有用的資源可用於 multicol 和相關的分片屬性。

如果您在項目中使用過 multicol,也許可以在評論中添加註釋,以分享我們可以使用該功能的其他方式。