在本文中,我們將探索 CSS Grid repeat() 函數的所有可能性,它允許我們高效地建立 Grid 列和行的模式,甚至無需媒體查詢就可以建立響應式佈局。
通過 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(<count>, <tracks>)
。(軌道是一列或一行的通用名稱)。
第一個引數可以是以下三種之一:
auto-fit
關鍵字auto-fill
關鍵字顯然,數位值設定了特定的軌道數。但是,auto-fit
和auto-fill
可以根據可用空間的大小,設定不同數量的軌道。這使得它們在沒有媒體查詢的響應式佈局中非常方便。下面我們將對它們進行詳細介紹。
第二個引數指定了要重複的軌道數。可選值包括:
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
,因此每一列的寬度與其包含的最長單詞一樣寬:
article {
grid-template-columns: repeat(3, min-content);
}
max-content
關鍵字的作用基本上與 min-content
相反:它根據網格單元格中最大的內容來確定軌道大小。在下面的演示中,列寬以內容最多的單元格為基礎:
article {
grid-template-columns: repeat(3, max-content);
}
與 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(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
之前,這種方法一直很有效。之後,內容就會開始脫離容器。我們很快就會看到如何獲得更好的效果。
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()
可以接收任何長度值,如 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];
}
更多的命名線內容可以檢視MDN。
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()
的結合一定會讓丘位元之箭射穿你頑固的心。通過它們的組合,我們無需使用媒體查詢即可建立真正的響應式佈局。
請看下列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()
來防止溢位,接下來我們就來看看它。
我們可以通過引入 min()
來控制小寬度下的情況。讓我們更新程式碼,使其看起來像這樣:
article {
grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
}
現在,最小列寬有兩個選項。瀏覽器會選擇最小值。一旦列的寬度小於 200px
,100%
就是較小的值,因此以它為準。這意味著剩下的一列現在被設定為寬度:100%,因此在寬度不斷減小的情況下,它仍能很好地適應其容器。
在我們目前看到的範例中,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()
函數可與 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))
請務必將這行程式碼牢記於心,因為它會派上大用場。
以上就是本文的全部內容,如果對你有所幫助,歡迎點贊、收藏、轉發~