如何使用Grid中的repeat函數

2023-09-01 09:00:27

在本文中,我們將探索 CSS Grid repeat() 函數的所有可能性,它允許我們高效地建立 Grid 列和行的模式,甚至無需媒體查詢就可以建立響應式佈局。

不要重複自己

通過 grid-template-columnsgrid-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-fitauto-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-contentmax-contentauto。不過,最好至少為一個引數使用長度值,因為關鍵字不應該同時作為兩個引數工作(不過我發現有時確實可以這樣做,例如 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。在較窄的裝置上,列會越來越窄。一旦達到 60px8vw 之間的較低值,就會停止縮小。因此,在窄螢幕上,我們仍然會發現內容懸掛在容器外;要做到完全響應式,還有很長的路要走。

如果你覺得 minmax()min()max() 的組合在現階段有點令人失望,請堅持住,它們的真正威力將在auto-fitauto-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-columnsgrid-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

auto-fitauto-fill關鍵字是設定固定軌道數的替代方法。它們告訴瀏覽器在給定空間內儘可能多地填充軌道。例如:

article {
  grid-template-columns: repeat(auto-fit, 150px);
}

在上面的演示中,div 的寬度被設定為 150px,那些無法在一行中顯示的 div 會被放到下一行。如果我們將auto-fit改為auto-fill,就不會發現有什麼不同,因為在這種情況下,它們的作用是一樣的。它們之間的區別只有在特殊情況下才會顯現出來。

在這一點上,auto-fitauto-fill都還不錯,但沒有什麼特別閃光的地方。當它們與 minmax()min() 結合使用時,真正的魔力才會開始發生,所以我們接著往下看。

結合使用

如果你還沒有愛上 repeat(),那麼 repeat()auto-fitminmax()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));
}

現在,最小列寬有兩個選項。瀏覽器會選擇最小值。一旦列的寬度小於 200px100% 就是較小的值,因此以它為準。這意味著剩下的一列現在被設定為寬度:100%,因此在寬度不斷減小的情況下,它仍能很好地適應其容器。

auto-fit和auto-fill的區別

在我們目前看到的範例中,auto-fitauto-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-columnsgrid-template-rows 一起作為較長宣告的一部分使用。我們在這裡遇到的大多數朋友--長度單位、min-contentmax-contentautominmax()fit-content() 和命名線--都可以與 repeat() 一起使用,也可以在其中使用。

有些組合是不允許使用軌跡引數的。例如,我們不能使用 repeat(auto-fill, 1fr) 這樣的引數。auto-fit 和彈性單位不能一起使用,因為我們需要在其中某個地方使用固定的測量值,例如 minmax(100px, 1fr)

正如我們所見,minmax() 函數可以巢狀 min()max() 函數。它還可以包含 automin-contentmax-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))

請務必將這行程式碼牢記於心,因為它會派上大用場。

以上就是本文的全部內容,如果對你有所幫助,歡迎點贊、收藏、轉發~