- 原文地址:Auto-Sizing Columns in CSS Grid:
auto-fill
vsauto-fit
- 原文作者:SARA SOUEIDAN
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:pot-code
- 校對者:ParadeTo、realYukiko
CSS Grid 之列寬自適應:auto-fill
vs auto-fit
除了顯式的指定列大小之外,CSS Grid 還有個非常強大的功能 —— 模式填充(repeat-to-fill)列然後對內容進行自動佈局。也就是說,開發者只需要指定列數,自適應方面的事情(視口尺寸小則顯示列數少,反之則多)交給瀏覽器來處理就行了,也不需要用媒體查詢。
上述功能完全可以用一條語句就能實現,這不禁讓我想起《哈利波特》裡,鄧布利多在霍拉斯家裡揮舞著他的巴拉拉小魔棒,然後“傢俱一件件跳回了原來的位置,裝飾品在半空中恢復了原形,羽毛重新鑽回軟墊裡,破損的圖書自動修復,整整齊齊地排列在書架上…”。
就是這麼神奇,而且還不用媒體查詢。這一切都歸功於 repeat()
方法和自動佈局的關鍵字。
其實這方面的技術文章很多,基本用法我就不在此贅述了,有興趣可以參考 Tim Wright 寫的 博文,個人極力推薦。
總之,repeat()
方法能根據你的需要分割出任意多個列。例如,如果你需要一個基於 12 列的網格系統,你可以這麼寫:
.grid {
display: grid;
/* 指定網格列數 */
grid-template-columns: repeat(12, 1fr);
}
複製程式碼
1fr
表示讓瀏覽器將網格空間進行均分,每列佔其一分,這樣就建立了 12 個寬度不固定但是相等的列。而且不管視口寬度如何,都會保持 12 列不變。但是,估計你也想到了,如果視口過窄,內容必然會被擠扁。
所以,這裡有必要設定列的最小寬度來保證容器不至於太窄,這裡需要用到 minmax()
方法。
grid-template-columns: repeat( 12, minmax(250px, 1fr) );
複製程式碼
按照 grid 的脾性,這麼做肯定會導致當前行內容溢位,即便視口在最小列寬的限制條件下實在無法容納這些列,這些列也不會自動換行,因為之前告訴過瀏覽器必須有 12 列。
為了實現換行,可以用 auto-fit
或 auto-fill
。
grid-template-columns: repeat( auto-fit, minmax(250px, 1fr) );
複製程式碼
這條語句讓瀏覽器自個兒去處理列寬和元素的換行,如果容器寬度不夠,元素會自動換行,也就不會導致溢位了。這裡仍舊用了 fr
單位,這樣的話,如果行內剩下的空間不足以容納另外一列時,已有的列能自動擴張佔滿一整行,不造成空間浪費。
乍一看名字,auto-fill
和 auto-fit
似乎是完全相反的兩個東西,實際上它們的區別相當微妙。
非要說的話,用 auto-fit
的時候,當前行的末尾留了不少空白,但是什麼時候留白,為什麼會留白呢?
來讓我們一探究竟。
Fill 和 Fit 的區別到底在哪?
在最近一個 CSS 研討會上,我是這麼總結 auto-fill
和 auto-fit
的區別的:
auto-fill
傾向於容納更多的列,所以如果在滿足寬度限制的前提下還有空間能容納新列,那麼它會暗中建立一些列來填充當前行。即使建立出來的列沒有任何內容,但實際上還是佔據了行的空間。
auto-fit
傾向於使用最少列數佔滿當前行空間,瀏覽器先是和auto-fill
一樣,暗中建立一些列來填充多出來的行空間,然後坍縮(collapse)這些列以便騰出空間讓其餘列擴張。
乍看起來還是挺懵逼的,稍後我會做一個視覺化圖來展示這些行為,這樣更容易理解一點。Firefox 有專門的 Grid 分析工具能幫助顯示元素和列的尺寸、位置(譯者注:用開發者工具拾取容器元素,在樣式側邊欄中的 display: grid
中的 grid
左側有個網格圖示,點一下就能顯式網格線條了)。
以 這裡 的 demo 為例。
還是用 repeat()
方法來定義列,設定其最小寬度為 100px,最大為 1fr
,這樣,如果存在額外空間,每一列分到的空間大小都相等。這裡讓列數自行計算,換行和自適應都交給瀏覽器處理。
第一個例子使用 auto-fill
關鍵字,第二個則是 auto-fit
。
.grid-container--fill {
grid-template-columns: repeat(auto-fill, minmax(100px, 1fr));
}
.grid-container--fit {
grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
}
複製程式碼
在特定的情況下,auto-fill
和 auto-fit
的效果是一樣的。
雖然看起來一樣,但骨子裡還是不同的。看起來一樣只是因為視口的寬度造成了這種巧合.
使它們產生不同的結果的關鍵點在於 grid-template-columns
中列數和列寬的設定,例子不同,產生的結果也會不同。
當視口的寬度大到能夠容納額外的列到當前行時,差別就會體現出來了。這時,瀏覽器會採用兩種方式來處理這種情況,怎麼處理取決於是否還有內容需要放到多出的列裡面。
所以,如果當前行還能再放得下一列,瀏覽器的行為如下:
- “我這還有空間再放一列,還有沒放進來的內容嗎(如:grid item)?如果有,OK,我再在當前行新增一列,如果視口太小,空間不夠了,我換一行再加”。
- 如果沒有多的內容:“是讓這新的一列尸位素餐呢,還是讓其坍縮讓其餘的列進行擴張來佔據它的空間呢?”
auto-fill
和 auto-fit
的出現解答了最後一個問題:在沒有多的內容的情況下,是坍縮還是任其佔位?
這是問題,同時也是選擇,最終取決於你的內容,以及你想該內容在響應式設計下如何表現。
下面來詳細解釋。為了形象、生動的表現出 auto-fill
和 auto-fit
的區別,請按我的步驟做,觀察螢幕上的變化。現在,我正在調整視口的大小,留出足夠的橫向空間,讓其能容納更多的列到當前行。牢記一點,例子中的兩行有完全相同的內容、相同的列數,唯一的區別是第一行用的是 auto-fill
,第二行用的是 auto-fit
。
這下應該清楚了吧,如果還是不明白,那我們繼續:
auto-fill
的做法:“來‘列’啊,給我把這行全佔了,列越多越好,我不介意有些個列完全是透明的 —— 看不到不代表不存在嘛。有空間就加列,有無內容無所謂,反正空間我是佔了(也就是說會用內容/grid item 來填充)。"
如上所述,auto-fill
儘可能容納多的列,即使有些列是空的,auto-fit
則稍顯不同。
auto-fit
的做法和 auto-fill
一樣,隨著視口寬度增大而增加列數,區別在於新增加的列都坍縮了(包括間隔 gap 在內)。用 Firefox 的 Grid 工具來視覺化這個過程再合適不過了,當視口的寬度增加時,新的列也被新增進來,grid 的線條也會增加,肉眼就能觀察得到全過程。
auto-fit
的做法:“先用已有的列進行填充,然後盡情擴張直到佔滿一整行空間。空白列不允許佔據多出的空間,這些空間要好好利用,應該讓已經填進去的列(內容/grid item)擴張自己來填充這些空間。”
有必要記住的一點是,在以上兩種情況中,多出來的列(無論最後是否坍縮)都不是隱式的列(implicit columns) —— 這在官方文件裡有特殊的含義。這裡新增的,或者說建立的列都在顯式 grid(explicit grid)裡面,和直接指明劃分出 12 列的 grid 是一樣的。所以,使用列數索引時, -1
會指向 grid 的末端,如果是隱式建立的,情況就不是這樣了。 給 Rachel Andrew 加雞腿,感謝他給出的這個小貼士。
總結
只有行的寬度大到能夠容納額外的列時,auto-fill
和 auto-fit
這兩者的區別才會體現出來。
用 auto-fit
時,內容區會自動拉伸以便佔滿一整行;另一方面,使用 auto-fill
的時候,瀏覽器對待空列和那些有實質內容的列一樣,一視同仁,允許其佔用行空間 —— 即使這些空列並無實質性內容,它們也還是會分得行空間的一杯羹,所以也能間接的影響那些有內容的列的大小,或者說寬度。
你更傾向於哪種行為取決於你的需求,說實在的,我也在想到底有哪些情況,auto-fill
會比 auto-fit
更適用一點。如果你恰好周圍有這樣的使用場景,希望能在評論區不吝賜教。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。