原文:When And How To Use CSS Multi-Column Layout
作者:Rachel Andrew
譯者:博軒
當我們把注意力都放在 CSS Grid
佈局和 CSS Flexbox
佈局的時候,經常忽略了另一種佈局方法。在本文中,我將介紹多列布局 - 通常稱爲 multicol
或者 “CSS Columns” 。通過這篇文章,你瞭解到使用 columns
的最佳實踐,以及一些使用 columns
的注意事項。
什麼是Multicol?
multicol
的基本思想是,你可以把一大塊內容帶到多個列中,就像報紙一樣。您可以使用兩個屬性中的其中一個來完成此操作。您可以使用 cloumn-count
屬性來指定內容的列數。還可以使用 column-width
屬性來指定理想的列寬,讓瀏覽器來決定合適的列數。
不論你的內容包含什麼樣的元素,當你將它轉換爲多列布局時,一切都將保持正常的內容流,但是將以列的形式展現。這使得 multicol
佈局與如今在瀏覽器中常見的其他佈局會有所不同。例如 Flexbox
和 Grid
,獲取容器元素中子元素,讓這些子元素參與到 flex
和 grid
的佈局中來。使用 multicol
,在每一列的內部,您還可以獲得正常的內容流。
在下面的例子中,我們正在使用 column-width
,最小列寬爲 14em
。Multicol
會儘可能多的分配寬度爲 14em
的列,然後,讓每一列分享剩餘的空間。每一列的寬度至少 14em
,除非,容器的寬度小於 14em
,那麼將只展示一列。multicol
也是 CSS
中首次出現的一種行爲,可以創建出列,同時也默認符合響應式的規則。您不必增加 CSS 查詢條件 (Media Queries
) ,修改每一個斷點的列數,而是制定一個最佳的寬度,讓瀏覽器自身來進行處理。
// 核心代碼摘錄
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
}
列樣式
當你使用列屬性(columns
)來創建佈局的時候,cloumns box
中的內容將無法定位。您無法使用 JavaScript
來進行定位,您也無法爲單個列來指定唯一的樣式,比如背景顏色,外邊距,內邊距等等。所有 column boxes
將保持相同的大小。你唯一可以做的事情,就是使用 column-rule
屬性來添加列之間的規則,該屬性的作用類似於 border
。您還可以使用 column-gap
屬性控制列之間的間隙,該屬性的默認值爲 1em
,但是您還可以將其改爲任何有效的長度單位。
// 核心代碼
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
column-gap: 2em;
column-rule: 1px solid #ccc;
}
這是 multicol
的基本功能。您可以將一大塊內容拆分爲列。內容將依次填充到每一列,並在內聯的方向創建這些列。您可以控制列之間的間隙以及規則,使用與 border
相同的取值即可。到目前爲止,上述所有內容在瀏覽器中得到了很好的支持,並且已經存在了很長時間,使得這個規範在向後兼容性方面非常安全。
您可能需要考慮使用列的其他一些事項,以及在Web上使用列時需要注意的一些潛在問題。
跨欄
有時候,您可能希望將某些內容分解爲列的同時,使用一個元素跨越這些列。將 columns-span
屬性用於 multicol
可以實現這一點。
下面的示例中,我使用一個 <blockquote>
元素來跨越列。請注意,在執行此操作時,內容會被分爲兩個區域,分別位於設置了 column-span
元素的上下兩個部分。內容不會跳過設置了 column-span
的元素。
column-span
屬性目前已在 Firefox 中實現,並且向後兼容。
// 核心代碼
blockquote {
font: 2em 'Berkshire Swash', cursive;
margin: 0;
column-span: all;
text-align: center;
}
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
column-gap: 2em;
column-rule: 1px solid #ccc;
}
要知道,目前的規範,column-span
的取值只有 all
或者 none
。如果你想實現報紙中的樣式,可以使用多列布局結合其他佈局來實現。在下面的示例中,我們實現了一個帶有兩個列軌道的網格容器(Grid)。左邊軌道的寬度是 2fr
,右邊軌道的寬度是 1fr
。我們將左邊的軌道變成了一個具有兩欄的 multicol
容器。它同樣包含了一個跨欄元素。
在右邊,我們將內容放入第二個 Grid
列軌道中。通過嘗試各種佈局方法,我們可以確切地找出適合手頭工作的佈局方法 - 不要害怕混合搭配!
// 核心代碼
.container {
max-width: 800px;
margin: 0 auto;
display: grid;
grid-gap: 1em;
grid-template-columns: 2fr 1fr;
align-items: start;
}
.container article {
column-count: 2;
column-gap: 2em;
column-rule: 1px solid #ccc;
}
.container aside {
border-left: 1px solid #ccc;
padding: 0 1em;
}
控制內容截斷
如果您的內容中包含標題,您可能希望避免標題出現在列的末端,而內容卻出現在了下一列中。再比如,您的內容中有一些帶有文字說明的圖片,那麼理想的情況下,圖片和他的文字說明,將保持一個整體展示,而不會被跨列分割。
當您將內容拆分爲列時,這種行爲被稱爲CSS片段模塊(Fragmentation) 。將內容分割成兩頁進行展示,就好像打印機選擇兩欄的打印模式一樣。因此,相比較Web上的其他佈局方法,multicol
是最接近Paged Media
的佈局方法。因此,我們可以使用屬於CSS2.1 的屬性 page-break
來實現這一點。
page-break-before
page-break-after
page-break-inside
最近,CSS片段模塊規範定義瞭如何爲各種片段模塊上下文設計的碎片化的屬性,規範包括 Paged Media
,multicol
和處於停滯狀態的區域樣式(Region Styling); 區域也會支持展示被分解(碎片化)連續的內容。通過使用這些通用屬性,它們可以應用於任何未來的CSS片段模塊上下文,就像 Flexbox
的對齊屬性被移動到 Box Alignment
規範中一樣,以便它們可以在 Grid
和 Block
佈局中使用。
break-before
break-after
break-inside
下面的示例中,我在 <figure>
元素中使用 break-inside avoid
屬性,防止圖像的標題和圖像分離。支持該屬性的瀏覽器中,我們應該可以看到聯合在一起的效果,即使這會導致列中的內容看起來不平衡。
// 核心代碼
figure {
margin: 0;
break-inside: avoid;
}
.container {
max-width: 800px;
margin: 0 auto;
column-width: 14em;
}
不幸的是,在 multicol
中對這些屬性的支持非常不完整。即使在支持的情況下,它們也應該被視爲一個建議,因爲在實際使用的時候,會提出很多要求來控制內容是否應該被分離,但是實際上瀏覽器並不會真正讓這些內容分離。在上面的示例中,我們定義了展示的優先級,但是當您在使用的時候還是要謹慎一些,僅在最需要的地方使用。
Columns 佈局的一些問題
我們在瀏覽網頁時,並沒有看到 multicol
被廣泛的使用,其原因是讀者的閱讀習慣,通常是自頂向下滾動閱讀的。對於使用英語,或其他垂直寫作的人來說,橫向的佈局並不是很好的閱讀體驗。
如果你固定容器的高度,例如使用 viewport
單位 vh
,當內容過多時,它會在內聯方向溢出,同時,你會得到一個橫向的滾動條。
這些情況都不是很理想。所以,在使用多列布局的時候,我們需要仔細的考慮每一欄的內容量。
Columns 塊溢出
在 Level 2
的規範當中,我們考慮如何使用一種方法,列的內容不會溢出,生成橫向的滾動條,而是在塊的方向上面生成新的列。這意味着您可以擁有一個具有高度的 multicol
容器,並且一旦內容超出了該容器的寬度,就會在下面創建一組新的列。這看起來有點像我們上面的跨越示例,但是,不是讓設置了column-span
的元素導致新的列框開始,而是由塊大小限制的容器寬度,從而解決溢出的問題。
此功能將使 multicol
對Web更有用。雖然我們現在還有一段距離,但您可以關注CSS工作組回購中的問題。如果您有此功能的其他用例,請發佈它們,它在設計新功能時非常有用。
今天,我們該如何使用 Multicol
?
使用當前規範,不建議將所有內容拆分爲列而不考慮滾動問題。但是,在某些情況下,multicol
對於 web
是理想的。在查看設計模式時,有足夠的示例k可供你參考。
摺疊小UI或文本元素
multicol
可以在任何需要佔用較少空間的項目列表的地方使用。例如,複選框的簡單列表或名稱列表。通常在這些情況下,訪問者不會讀取一列然後返回到下一列的頂部,而是掃描內容以選中要單擊的複選框或要選擇的項目。即使您確實創建了滾動體驗,這個問題也依然存在。
您可以在 DonarMuseum網站 上看到 Sander de Jong以這種方式使用的 multicol
示例。
確認的少量內容
有時,我們設計一個網站,我們知道某些內容區域相對較小,並且適合大多數屏幕展示,且不需要滾動。我在 Notist演示頁面 使用了 multicol
,用於介紹演講。
Andy Clarke爲 Equfund網站設計了一個可愛的例子。
爲了避免非常小的屏幕導致頁面出現滾動,就像寬度一樣,您可以使用媒體查詢來檢查高度。對於超出最小高度的內容,您可以在斷點處設置 min-height
,來避免用戶使用較小設備時所帶來的較差體驗。
瀑布流(MASONRY-LIKE)的內容顯示
多列布局工作得很漂亮的另一個地方是,如果要創建瀑布流的內容顯示。Multicol
是目前唯一一種,可以創建不定高度的佈局方法。Grid
佈局要麼會留下間隙,要麼拉伸項目以形成嚴格的二維網格。
Veerle Pieters 有一個很好的例子,就是在她的靈感頁面上以這種方式使用multicol
。
Grid 和 Flexbox 的備選方案
這些 column-
屬性還可以用作 Grid
和 Flex
佈局的備選方案。如果在容器上指定其中一個屬性,則使用 display: flex
或 display: grid
將刪除任何列行爲,將該容器轉換爲 Flex
或 Grid
佈局。例如,如果你有一個使用 Grid
佈局的卡片佈局,如果它在列中而不是在頁面上運行,那麼佈局就是可讀的,你可以使用 multicol
作爲簡單的後備。不支持 Grid
的瀏覽器將獲得 multicol
顯示,支持 Grid
的瀏覽器將獲得 Grid Layout
。
別忘了Multicol!
我經常回答 Grid
和 Flexbox
的問題,答案是不使用 Grid
或 Flexbox
,而是試試 Multicol
。您可能不會在每個站點上使用它,但是當您遇到本文中提到的場景時,它可能非常有用。在MDN上有關於 multicol和CSS片段模塊的有用資源。
如果您在項目中有 multicol
的其他使用場景,也歡迎留言分享!
本文已經聯繫原文作者,並授權翻譯,轉載請保留原文鏈接