[譯] CSS Grid 之列寬自適應:`auto-fill` vs `auto-fit`

CSS Grid 之列寬自適應:auto-fill vs auto-fit

除了顯式的指定列大小以外,CSS Grid 還有個很是強大的功能 —— 模式填充(repeat-to-fill)列而後對內容進行自動佈局。也就是說,開發者只須要指定列數,自適應方面的事情(視口尺寸小則顯示列數少,反之則多)交給瀏覽器來處理就好了,也不須要用媒體查詢。css

上述功能徹底能夠用一條語句就能實現,這不由讓我想起《哈利波特》裏,鄧布利多在霍拉斯家裏揮舞着他的巴拉拉小魔棒,而後「傢俱一件件跳回了原來的位置,裝飾品在半空中恢復了原形,羽毛從新鑽回軟墊裏,破損的圖書自動修復,整整齊齊地排列在書架上…」。前端

就是這麼神奇,並且還不用媒體查詢。這一切都歸功於 repeat() 方法和自動佈局的關鍵字。android

其實這方面的技術文章不少,基本用法我就不在此贅述了,有興趣能夠參考 Tim Wright 寫的 博文,我的極力推薦。ios

總之,repeat() 方法能根據你的須要分割出任意多個列。例如,若是你須要一個基於 12 列的網格系統,你能夠這麼寫:git

.grid {
   display: grid;

  /* 指定網格列數 */
  grid-template-columns: repeat(12, 1fr);
}
複製代碼

1fr 表示讓瀏覽器將網格空間進行均分,每列佔其一分,這樣就建立了 12 個寬度不固定可是相等的列。並且無論視口寬度如何,都會保持 12 列不變。可是,估計你也想到了,若是視口過窄,內容必然會被擠扁。github

因此,這裏有必要設置列的最小寬度來保證容器不至於太窄,這裏須要用到 minmax() 方法。後端

grid-template-columns: repeat( 12, minmax(250px, 1fr) );
複製代碼

按照 grid 的脾性,這麼作確定會致使當前行內容溢出,即使視口在最小列寬的限制條件下實在沒法容納這些列,這些列也不會自動換行,由於以前告訴過瀏覽器必須有 12 列。瀏覽器

爲了實現換行,能夠用 auto-fitauto-fillbash

grid-template-columns: repeat( auto-fit, minmax(250px, 1fr) );
複製代碼

這條語句讓瀏覽器自個兒去處理列寬和元素的換行,若是容器寬度不夠,元素會自動換行,也就不會致使溢出了。這裏仍舊用了 fr 單位,這樣的話,若是行內剩下的空間不足以容納另一列時,已有的列能自動擴張佔滿一整行,不形成空間浪費。工具

乍一看名字,auto-fillauto-fit 彷佛是徹底相反的兩個東西,實際上它們的區別至關微妙。

非要說的話,用 auto-fit 的時候,當前行的末尾留了很多空白,可是何時留白,爲何會留白呢?

來讓咱們一探究竟。

Fill 和 Fit 的區別到底在哪?

在最近一個 CSS 研討會上,我是這麼總結 auto-fillauto-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-fillauto-fit 的效果是同樣的。

雖然看起來同樣,但骨子裏仍是不一樣的。看起來同樣只是由於視口的寬度形成了這種巧合.

使它們產生不一樣的結果的關鍵點在於 grid-template-columns 中列數和列寬的設置,例子不一樣,產生的結果也會不一樣。

當視口的寬度大到可以容納額外的列到當前行時,差異就會體現出來了。這時,瀏覽器會採用兩種方式來處理這種狀況,怎麼處理取決因而否還有內容須要放到多出的列裏面。

因此,若是當前行還能再放得下一列,瀏覽器的行爲以下:

  1. 「我這還有空間再放一列,還有沒放進來的內容嗎(如:grid item)?若是有,OK,我再在當前行添加一列,若是視口過小,空間不夠了,我換一行再加」。
  2. 若是沒有多的內容:「是讓這新的一列尸位素餐呢,仍是讓其坍縮讓其他的列進行擴張來佔據它的空間呢?」

auto-fillauto-fit 的出現解答了最後一個問題:在沒有多的內容的狀況下,是坍縮仍是任其佔位? 這是問題,同時也是選擇,最終取決於你的內容,以及你想該內容在響應式設計下如何表現。

下面來詳細解釋。爲了形象、生動的表現出 auto-fillauto-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-fillauto-fit 這二者的區別纔會體現出來。

auto-fit 時,內容區會自動拉伸以便佔滿一整行;另外一方面,使用 auto-fill 的時候,瀏覽器對待空列和那些有實質內容的列同樣,一視同仁,容許其佔用行空間 —— 即便這些空列並沒有實質性內容,它們也仍是會分得行空間的一杯羹,因此也能間接的影響那些有內容的列的大小,或者說寬度。

你更傾向於哪一種行爲取決於你的需求,說實在的,我也在想到底有哪些狀況,auto-fill 會比 auto-fit 更適用一點。若是你剛好周圍有這樣的使用場景,但願能在評論區不吝賜教。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索