如何使用Grid中的repeat函數
不要重復自己
通過 grid-template-columns 和 grid-template-rows 屬性,我們可以顯式地設置網格中的行數和列數,并指定它們的大小。如果我們希望多行和/或多列的大小相同,這可能會變得重復。
repeat()函數可以將我們從重復中解救出來。舉個例子,我們可能會這么寫:
grid-template-columns: 1fr 1fr 1fr 1fr 1fr;
使用repeat(),可以這么寫:
grid-template-columns: repeat(5, 1fr);
在上面的例子中,repeat()函數可以讓我們指定需要多少列(5列),以及列的大小(1fr,即可用空間的幾分之一)。
這樣,我們的代碼就會更高效、更易讀。這只是一個簡單的例子。下面我們將看到,我們還可以用 repeat() 函數做很多事情。
下面的截圖顯示了上述代碼的一個簡單演示。一篇包含十個 div 的文章分為五列。
圖片
repeat函數的的選項
實際上,我們可以在 repeat() 的括號內做很多事情。它接收兩個參數,中間用逗號隔開。第一個參數代表"計數",第二個參數代表"軌道":repeat(<count>, <tracks>)。(軌道是一列或一行的通用名稱)。
第一個參數可以是以下三種之一:
- 數字(比如1,2,3)
- auto-fit關鍵字
- auto-fill關鍵字
顯然,數字值設定了特定的軌道數。但是,auto-fit和auto-fill可以根據可用空間的大小,設置不同數量的軌道。這使得它們在沒有媒體查詢的響應式布局中非常方便。下面我們將對它們進行詳細介紹。
第二個參數指定了要重復的軌道數。可選值包括:
- 長度值,可使用單位包括fr、px、em、%和ch等等
- min-content關鍵字
- max-content關鍵字
- auto關鍵字
- minmax()函數,其可以嵌套min()或者max()函數
- fit-content()函數
- 命名線
正如你所看到的,這個參數有很多可能的選項,它們看起來可能有點混亂,尤其是當幾個選項組合在一起的時候。在此,我們將盡量把事情簡單化,以免陷入混亂。在大多數情況下,軌道參數是相當簡單和直觀的。
設置重復列
在探索 repeat() 可以使用的各種參數之前,值得注意的是 repeat() 可以用來創建列模式。
例如,請看下面這段有六列網格的超長代碼:
article {
grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr;
}
可以使用repeat()這么改寫:
article {
grid-template-columns: repeat(3, 1fr 2fr);
}
這會告訴瀏覽器重復一個模式三次--先是 1fr 寬的一列,然后是 2fr 寬的一列。
圖片
使用長度值
我們已經在 repeat() 中使用過 1fr 的長度值。使用 fr 單位的好處是,它可以根據可用空間確定軌道的大小,而無需擔心可用空間的多少。不過,我們也可以根據需要使用其他長度單位。
例如,讓我們設置三列軌道,并賦予它們 120 像素的寬度:
article {
grid-template-columns: repeat(3, 120px);
}
下面是結果:
圖片
現在列的寬度是固定的,即使容器太窄也不會改變。
使用min-content關鍵字
min-content 關鍵字可將軌道設置為與其最小內容一樣寬或一樣高。在下面的演示中,我們有三列,每一列都設置為 min-content,因此每一列的寬度與其包含的最長單詞一樣寬:
article {
grid-template-columns: repeat(3, min-content);
}
圖片
使用max-content關鍵字
max-content 關鍵字的作用基本上與 min-content 相反:它根據網格單元格中最大的內容來確定軌道大小。在下面的演示中,列寬以內容最多的單元格為基礎:
article {
grid-template-columns: repeat(3, max-content);
}
圖片
使用auto關鍵字
與 repeat() 一起使用時,auto 關鍵字的最大值為 max-content,最小值為 min-content。
請看下面的列模式:
article {
grid-template-columns: repeat(3, auto 1fr);
}
在這里,我們將有六列,每一奇數列的寬度設置為 auto。在下面的演示中,我們可以看到,在有足夠空間的情況下,帶有"auto"文本的 div 將在max-content時達到最大寬度,而 1fr div 則共享剩余空間。當瀏覽器變窄時,"auto"列繼續變窄,直到達到min-content閾值。
圖片
在上面的演示中,只有當每一列達到min-content閾值時,div 才會開始溢出容器。(也就是說,文本無法再繼續被包覆)。
注意:auto 只有在與其他值混合時才會出現上述行為。如果單獨使用 repeat(3, auto),其行為就像我們設置 repeat(3, 1fr) 一樣。
使用minmax()函數
minmax() 函數本身需要兩個參數--最小值和最大值,中間用逗號隔開。因此,通過 minmax(),我們可以在靈活的環境中為軌道設置一系列可能的尺寸。
例如,我們可以將一列設置為 minmax(40px, 100px),這意味著其最小寬度為 40px,最大寬度為 100px。
minmax() 的兩個參數都可以使用長度值,如 fr、px、em、% 和 ch,以及 min-content、max-content 和 auto。不過,最好至少為一個參數使用長度值,因為關鍵字不應該同時作為兩個參數工作(不過我發現有時確實可以這樣做,例如 minmax(min-content,max-content))。
下面代碼設置了五列,每一列的最小寬度為60px,最大寬度為1fr:
article {
grid-template-columns: repeat(5, minmax(60px, 1fr));
}
圖片
在達到最小寬度 60px 之前,這種方法一直很有效。之后,內容就會開始脫離容器。我們很快就會看到如何獲得更好的效果。
使用min()或者max()
minmax() 函數的參數也可以是 min() 或 max() 函數。這兩個函數都接收兩個參數。min()函數應用兩個值中較小的值,而 max() 函數應用較大的值。這在響應式環境中非常有用。
比如說:
article {
grid-template-columns: repeat(5, minmax(min(60px, 8vw), 1fr));
}
圖片
上面的代碼設置了五列。在寬屏幕瀏覽器上,五列的間距均為 1fr。在較窄的設備上,列會越來越窄。一旦達到 60px 和 8vw 之間的較低值,就會停止縮小。因此,在窄屏幕上,我們仍然會發現內容懸掛在容器外;要做到完全響應式,還有很長的路要走。
如果你覺得 minmax()、min() 和 max() 的組合在現階段有點令人失望,請堅持住,它們的真正威力將在auto-fit和auto-fill時顯現。
使用fit-content()函數
fit-content()函數接收一個參數,該參數代表軌道可增長到的最大尺寸。fit-content() 可以接收任何長度值,如 fr、px、em、% 和 ch。
比如說,如果我們設置了三列,并設置了 fit-content(120px),那么列寬在 120px 之前都將是響應式的:
article {
grid-template-columns: repeat(3, fit-content(120px));
}
圖片
使用命名線
在網格布局中,軌道周圍的垂直線和水平線默認是編號的。在設置 grid-template-columns 和 grid-template-rows 時,我們可以為這些線命名。這樣,在網格上放置內容時,就可以更容易地定位這些線(因為我們不必去計算網格線)。
下面是一個示例。命名行是方括號([])中的點位:
article {
grid-template-columns: [sidebar] 300px [content-start] 1fr [content-end];
}
上面的代碼提供了兩列。最左邊的垂直網格線(數字 1)稱為"sidebar",中間的網格線(數字 2)稱為"content-start",最后的網格線(數字 3)稱為 "content-end"。
我們還可以在 repeat() 函數中使用命名線:
article {
grid-template-columns: repeat(5, [yin] 1fr [yang]);
}
這意味著,現在我們的每一列左邊都有一條線稱為"yin",右邊都有一條線稱為"yang"。
圖片
如果每一行都有相同的名稱,似乎會增加工作難度,但我們仍然可以將它們分別作為目標。例如:
- 我們可以用 grid-column: yin 來定位第一條yin線
- 我們可以用 grid-column: yin 2 來定位第二條yin線
- 我們可以設置一列從第二條yin線起跨三行: grid-column: yin 2 / span 3
- 我們可以通過 grid-column: yin 2 / yang -1 設置一列,從第二條yin線開始,一直跨到末尾。
在 repeat() 中命名線可能在 repeat() 與其他值混合時最有用,比如這樣:
article {
grid-template-columns: [main-start] auto repeat(5, [yin] 1fr [yang]) [sidebar] 300px [main-end];
}
圖片
更多的命名線[1]內容可以查看MDN。
使用auto-fit和auto-fill
auto-fit和auto-fill關鍵字是設置固定軌道數的替代方法。它們告訴瀏覽器在給定空間內盡可能多地填充軌道。例如:
article {
grid-template-columns: repeat(auto-fit, 150px);
}
圖片
在上面的演示中,div 的寬度被設置為 150px,那些無法在一行中顯示的 div 會被放到下一行。如果我們將auto-fit改為auto-fill,就不會發現有什么不同,因為在這種情況下,它們的作用是一樣的。它們之間的區別只有在特殊情況下才會顯現出來。
在這一點上,auto-fit和auto-fill都還不錯,但沒有什么特別閃光的地方。當它們與 minmax() 和 min() 結合使用時,真正的魔力才會開始發生,所以我們接著往下看。
結合使用
如果你還沒有愛上 repeat(),那么 repeat() 與 auto-fit、minmax() 和 min() 的結合一定會讓丘比特之箭射穿你頑固的心。通過它們的組合,我們無需使用媒體查詢即可創建真正的響應式布局。
使用auto-fit和minmax()
請看下列CSS:
article {
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
在當前示例中,minmax()設置了最大列寬為200px,最小列寬為1fr。
圖片
每個 div 的寬度必須至少為 200px。如果右側有額外空間(小于 200 像素),div 會展開以填充空間。如果我們拓寬瀏覽器,一旦又有 200 像素的空間,就會在行中添加另一個 div。同樣的情況也會反過來發生:當我們縮小瀏覽器時,一旦沒有至少 200px 的空間可以容納,行中的最后一個 div 就會進入下一行。一旦該 div 掉下去,其余的 div 就會展開以填滿該行。
同樣,如果我們把auto-fit換成auto-fill,就會看到相同的行為。
不過,這個例子有一個限制。如果我們將瀏覽器窗口設置得足夠窄,最終就會出現單列。當這一列的寬度小于 200px 時,div 就會開始溢出其容器。
圖片
我們可以通過引入 min() 來防止溢出,接下來我們就來看看它。
使用auto-fit,minmax()和min()
我們可以通過引入 min() 來控制小寬度下的情況。讓我們更新代碼,使其看起來像這樣:
article {
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
}
現在,最小列寬有兩個選項。瀏覽器會選擇最小值。一旦列的寬度小于 200px,100% 就是較小的值,因此以它為準。這意味著剩下的一列現在被設置為寬度:100%,因此在寬度不斷減小的情況下,它仍能很好地適應其容器。
auto-fit和auto-fill的區別
在我們目前看到的示例中,auto-fit和auto-fill似乎沒有任何區別。區別只出現在某些情況下,我們現在就來簡單介紹一下。
我們將剝離演示 HTML,使其只有四個 div,并設置以下 CSS:
article {
grid-template-columns: repeat(auto-fill, minmax(min(100px, 100%), 1fr));
}
下圖顯示了auto-fill后的效果。
圖片
瀏覽器正在計算容器中可以容納多少個 div,并為它們留出空間。現有的每個 div 都有 110px 寬,左側和右側的空間也是如此。
讓我們切換到auto-fit:
article {
grid-template-columns: repeat(auto-fit, minmax(min(100px, 100%), 1fr));
}
下圖顯示了auto-fit后的效果。
圖片
使用auto-fit功能時,瀏覽器也會為更多的 div 計算空間,但隨后會將空間折疊為零寬度,并讓現有的 div 展開以占據所有空間。在上圖中,你可以看到末端列行的編號仍然是 8,而 8 則堆疊在網格行 7、6 和 5 的上方。
那么我們該如何看待這一切呢?實際上,在大多數甚至所有情況下,我們都希望使用auto-fit功能,因為我們并不經常希望在可以用于內容的空間保持空閑。
關于 repeat() 的實用知識
如上所述,repeat()函數可與 grid-template-columns 和 grid-template-rows 一起作為較長聲明的一部分使用。我們在這里遇到的大多數朋友--長度單位、min-content、max-content、auto、minmax()、fit-content() 和命名線--都可以與 repeat() 一起使用,也可以在其中使用。
有些組合是不允許使用軌跡參數的。例如,我們不能使用 repeat(auto-fill, 1fr) 這樣的參數。auto-fit 和彈性單位不能一起使用,因為我們需要在其中某個地方使用固定的測量值,例如 minmax(100px, 1fr)。
正如我們所見,minmax() 函數可以嵌套 min() 或 max() 函數。它還可以包含 auto、min-content、max-content 中的一個,但不能包含兩個。例如,我們可以使用 minmax(50px, max-content),但不能使用 minmax(min-content, max-content)(不過老實說,我發現這些組合中的某些似乎確實有效)。
repeat() 不能嵌套。因此,我們不能在 repeat() 中使用 repeat()。不過我們并排使用 repeat() 函數,例如 repeat(5, 1fr) 100px repeat(2, 50px)。
總結
repeat() 函數是一種非常有用的工具,可用于高效布局網格列和行的重復模式。只需一行代碼,它就能在不使用媒體查詢的情況下創建完全響應式的布局。
在大多數情況下,你不需要對 repeat() 進行過多的深入研究。它最令人印象深刻的功能可以用這樣一個基本示例來概括:
repeat(auto-fit, minmax(min(50px, 100%), 1fr))
請務必將這行代碼牢記于心,因為它會派上大用場。
本文譯自:https://www.sitepoint.com/css-grid-repeat-function/