了解 CSS 網格:創建網格容器

已發表: 2022-03-10
快速總結 ↬在一個新系列中,Rachel Andrew 分解了 CSS 網格佈局規範。 這一次,我們將詳細了解創建網格容器時會發生什麼,以及可應用於容器以塑造網格的各種屬性。

這是 Smashing Magazine 專注於 CSS 網格佈局的新系列的開始。 雖然自 2017 年以來 Grid 已在瀏覽器中可用,但許多開發人員還沒有機會在項目中使用它。 似乎有很多與 CSS 網格佈局相關的新屬性和值。 這可以使它看起來勢不可擋。 但是,很多規範詳細說明了做事的替代方法,這意味著您不必學習整個規範即可開始使用。 本系列旨在將您從網格新手轉變為專家 - 在此過程中提供許多實際使用技巧。

這篇最初的文章將介紹創建網格容器時會發生什麼,以及可以在父元素上使用來控制該網格的各種屬性。 您會發現有幾個用例僅通過您應用於網格容器的屬性來實現。

在本文中,我們將介紹:

  • 使用display: griddisplay: inline-grid創建一個網格容器,
  • 使用grid-template-columnsgrid-template-rows設置列和行,
  • 使用grid-auto-columnsgrid-auto-rows控制隱式軌道的大小。

  • 第 1 部分:創建網格容器

  • 第 2 部分:網格線

  • 第 3 部分:網格模板區域

跳躍後更多! 繼續往下看↓

創建網格容器

Grid 和 Flexbox 一樣,是 CSS display屬性的一個值。 因此,要告訴瀏覽器您要使用網格佈局,請使用display: grid 。 完成此操作後,瀏覽器將為您提供帶有display: grid的元素上的塊級框,並且任何直接子級都將開始參與網格格式化上下文。 這意味著它們的行為類似於網格項,而不是普通的塊和內聯元素。

但是,您可能不會立即在頁面上看到差異。 由於您尚未創建任何行或列,因此您有一個單列網格。 正在生成足夠的行來容納所有直接子級,並且它們在該單列中一個接一個地顯示。 從視覺上看,它們看起來就像塊元素。

如果您有任何未包含在元素中的文本字符串以及網格容器的直接子元素,您將看到不同之處,因為該字符串將被包含在匿名元素中並成為網格項。 任何通常是內聯元素的元素,例如 span,一旦其父元素是網格容器,也將成為網格項。

下面的例子有兩個塊級元素,加上一個文本字符串,字符串中間有一個跨度。 我們最終得到五個網格項目:

  • 兩個div元素,
  • 跨度之前的文本字符串,
  • 跨度,
  • 跨度之後的文本字符串。

請參閱鋼筆網格容器:直接子元素和文本字符串成為 Rachel Andrew (@rachelandrew) 在 CodePen 上的網格項。

請參閱鋼筆網格容器:直接子元素和文本字符串成為 Rachel Andrew (@rachelandrew) 在 CodePen 上的網格項。

如果您使用 Firefox Grid Inspector 檢查網格,您可以看到已為項目創建的五行軌道。

具有五行的單列網格
Grid Inspector 可幫助您查看已創建的行數

您還可以使用display: inline-grid創建內聯網格; 在這種情況下,您的網格容器將成為一個內聯級框。 但是,直接子項仍然是網格項,其行為方式與塊級框內的網格項相同(它只是外部顯示類型)。 這就是為什麼當網格容器與頁面上的其他框並排時,它的行為方式與上面一樣。

下一個示例有一個網格,後跟一個文本字符串,因為這是一個內聯網格,文本可以顯示在它旁邊。 內聯級事物不會像塊級事物那樣拉伸以佔用內聯維度中的所有空間。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:inline-grid。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:inline-grid。

注意將來,我們將能夠更好地描述我們的佈局,使用display: block grid來創建我們的塊級容器,使用display: inline grid來創建一個內聯級容器。 您可以在我的文章“深入了解 DISplay 屬性:Display 的兩個值”中了解對顯示規範的這種更改。

列和行

為了得到看起來像網格的東西,我們需要添加列和行。 這些是使用grid-template-columnsgrid-template-rows屬性創建的。 這些屬性在規範中定義為接受一個稱為track-list的值。

這些屬性以空格分隔的軌道列表的形式指定網格的行名稱和軌道大小功能。 grid-template-columns 屬性指定網格列的軌道列表,而 grid-template-rows 指定網格行的軌道列表。

一些有效的曲目列表值如下:

grid-template-columns: 100px 100px 200px; 創建一個三列網格:第一列是 100px,第二列是 100px,第三列是 200px。
grid-template-columns: min-content max-content fit-content(10em) 創建一個三列網格:第一列是該軌道的min-content大小,第二列是max-content大小。 第三個是max-content ,除非內容大於 10em,在這種情況下,它被限制為 10em。
grid-template-columns: 1fr 1fr 1fr; 使用fr單位創建一個三列網格。 網格容器中的可用空間被分成三部分,並在三列之間共享。
grid-template-columns: repeat(2, 10em 1fr); 創建一個四列網格,其重複模式為10em 1fr 10em 1fr ,因為 repeat 語句中的 track-list 重複了兩次。
grid-template-columns: repeat(auto-fill, 200px); 如果有空閒空間,則使用盡可能多的 200px 列填充容器,在最後留下一個間隙。
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); 用盡可能多的 200px 列填充容器,然後在創建的列之間平均分配剩餘空間。
grid-template-columns: [full-start] 1fr [content-start] 3fr [content-end] 1fr [full-end]; 創建一個三列網格:第一列和第三列各有 1 部分可用空間,而中間列有 3 部分。 通過將行名放在方括號中來命名行。

如您所見,有很多方法可以創建曲目列表! 讓我們來看看這些都是如何工作的,並提供一些提示,說明您為什麼要使用它們。

使用長度單位

您可以使用任何長度單位或百分比來創建曲目。 如果軌道的大小加起來小於網格容器中可用的大小,則默認情況下,軌道將在容器的開始處排列,備用空間將到最後。 這是因為align-contentjustify-content的默認值是start 。 您可以使用對齊屬性將網格軌道隔開,或者將它們移動到容器的末尾,我在我的文章“如何在 CSS 中對齊事物”中對此進行了詳細說明。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:長度單位。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:長度單位。

您還可以使用關鍵字min-contentmax-contentfit-content() 。 使用min-content將為您提供盡可能小的軌道而不會導致溢出。 因此,當用作列大小時,內容將盡可能軟換行。 軌道成為列中最長單詞或最大固定大小元素的大小。

使用max-content將導致內容根本不進行任何軟包裝。 在列中,任何文本字符串都會展開,這可能會導致溢出。

fit-content關鍵字只能通過傳入一個值來使用。 該值成為該軌道將增長到的最大值。 因此,軌道將像max-content一樣,內容展開並伸展,直到達到您傳入的值。此時,它將開始正常換行。 所以你的軌跡可能小於你傳入的值,但永遠不會更大。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container:min-content、max-content、fit-content()。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container:min-content、max-content、fit-content()。

您可以在我的文章“那個盒子有多大? 了解 CSS 佈局中的大小調整”。

如果您最終得到的軌道佔用的空間超過容器中的空間,它們就會溢出。 如果你使用百分比,那麼與基於百分比的浮動或彈性佈局一樣,如果你想避免溢出,你需要注意總百分比不超過 100%。

fr單位

Grid Layout 包含一種可以讓您自己計算百分比的方法——使用fr單位進行軌道大小調整。 該單位不是長度,因此不能與calc()結合使用; 它是一個彈性單元,代表網格容器中的可用空間。

這意味著使用1fr 1fr 1fr的曲目列表; 可用空間分為三個,並在軌道之間平均共享。 使用2fr 1fr 1fr的軌道列表,可用空間分為四部分,兩部分分配給軌道一——軌道二和三各有一部分。

請參閱 CodePen 上的 Pen Grid Container:Rachel Andrew (@rachelandrew) 的 fr。

請參閱 CodePen 上的 Pen Grid Container:Rachel Andrew (@rachelandrew) 的 fr。

需要注意的是,默認情況下共享的是可用空間,而不是容器中的總空間。 如果您的任何曲目包含固定大小的元素或無法換行的長單詞,則將在空間共享之前對其進行佈局。

在下一個示例中,我刪除了ItemThree單詞之間的空格。 這形成了一個長而牢不可破的字符串,因此空間分配發生在該項目的佈局被考慮之後。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container:fr 與更大的內容。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container:fr 與更大的內容。

您可以將fr單元與固定長度的軌道混合,這就是它變得非常有用的地方。 例如,您可以擁有一個具有兩個固定大小的列和一個可伸展的中心區域的組件:

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container:混合 fr 單位和固定大小的軌道。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container:混合 fr 單位和固定大小的軌道。

您可以將一個軌道設置為fit-content(300px)並將另一個軌道設置為 1fr。 這使得組件在第一個軌道中可以有小於 300px 的東西,在這種情況下,它只佔用它需要的空間,而fr單元擴展以佔用其餘空間。

如果您添加更大的內容(例如具有max-width: 100%的圖像),第一個軌道將在 300px 處停止增長,而fr單元將佔據其餘空間。 將fr單元與 fit-content 混合是一種為您的站點製作一些非常靈活的組件的方法。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:混合 fr 和 fit-content()。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:混合 fr 和 fit-content()。

重複()函數

在您的曲目列表中使用repeat()可以節省一遍又一遍地輸入相同的值或值。 例如以下兩行是相同的:

 grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr; grid-template-columns: repeat(12, 1fr);

使用repeat()時,逗號之前的值是重複逗號之後的曲目列表的次數。 該曲目列表可以是多個值。 這意味著您可以重複軌道模式。

您可以將repeat()函數用於曲目列表的一部分。 例如,以下行將為您提供 1fr 軌道、3 200px 軌道和最終 1fr 軌道。

 grid-template-columns: 1fr repeat(3,200px) 1fr

除了逗號前的數字表示固定的重複次數外,還可以使用關鍵字auto-fillauto-fit 。 使用這些關鍵字之一意味著您的網格容器將填充盡可能多的軌道,而不是固定數量的軌道。

請參閱鋼筆網格容器:Rachel Andrew (@rachelandrew) 在 CodePen 上的自動填充。

請參閱鋼筆網格容器:Rachel Andrew (@rachelandrew) 在 CodePen 上的自動填充。

使用固定長度單位意味著,除非容器能夠準確地除以該大小,否則您最終會剩下一些空閒空間。 在上面的例子中,我的容器是 500px 寬,所以我得到了兩個 200px 的軌道加上最後的空間。

我們可以使用另一個網格函數來使該值最小化,任何空閒空間都分佈在所有軌道上。 minmax()函數採用最小和最大大小。 最小 200px 和最大 1fr,我們可以得到盡可能多的 200px 軌道,因為最大值是 1fr,我們已經知道這將平均分配空間,額外的分配在軌道上。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:auto-fill 和 minmax()。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:auto-fill 和 minmax()。

我提到有兩個可能的關鍵字: auto-fillauto-fit 。 如果您有足夠的內容來填充第一行單元格,那麼這些單元格的行為方式將完全相同。 但是,如果您不這樣做(例如,如果我們在上面的容器中刪除了除一項之外的所有項目),那麼它們的行為會有所不同。

即使沒有內容進入,使用auto-fill將保持可用的軌道大小。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container: auto-fill and minmax() with one item。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container: auto-fill and minmax() with one item。

相反,如果您使用auto-fit ,則空軌道將被折疊:

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container: auto-fit 和 minmax() 以及一項。

請參閱 Rachel Andrew (@rachelandrew) 在 CodePen 上的 Pen Grid Container: auto-fit 和 minmax() 以及一項。

通過使用 Firefox Grid Inspector,您可以看到軌道仍然存在,但已折疊為零。 我們網格的終點線仍然是第 3 行,因為我們可以容納兩條軌道。

單個網格項填充容器,網格檢查器突出顯示列線
軌道還在,但倒塌了

命名線

我上面的最後一個示例使用了命名行方法。 使用網格時。 你總是有行號,但是,你也可以命名這些行。 行在方括號內命名。 一行可以有多個名稱; 在這種情況下,一個空格將它們分開。 例如,在以下曲目列表中,我的所有行都有兩個名稱。

 grid-template-columns: [main-start sidebar-start] 1fr [sidebar-end content-start] 4fr [content-end main-end]

您可以將您的行命名為您喜歡的任何名稱,除了span一詞,因為它是一個保留字,因為在將項目放置在網格上時會使用它。

注意在本系列的下一篇文章中,我將更多地討論基於行的放置以及如何使用命名行。 同時,請閱讀我關於“在 CSS 網格佈局中命名事物”的文章,以幫助您了解有關該主題的更多信息。

顯式與隱式網格

使用帶有軌道列表的grid-template-columnsgrid-template-rows創建網格時,您正在創建所謂的顯式網格。 這是您定義的網格,它具有您為每個軌道選擇的大小。

如果您的項目多於無法容納的數量,或者將項目放置在您創建的網格邊界之外,則 Grid 將在隱式網格中創建軌道。 默認情況下,這些隱式軌道將自動調整大小。 當我聲明display: grid父元素上的網格和網格創建的行,每個項目一個。 我沒有定義這些行,但由於有網格項目,所以創建行軌道是為了讓它們有去處。

您可以使用grid-auto-rowsgrid-auto-columns屬性設置隱式行或列的大小。 這些屬性採用跟踪列表,因此如果您希望所有隱式列的高度至少為 200 像素,但如果內容更多則增加,您可以使用以下內容:

 grid-auto-rows: minmax(200px, auto)

如果您希望第一個隱式行自動調整大小,第二個是min-content大小,依此類推(直到所有網格項目都被容納),您可以傳入多個值:

grid-auto-rows: auto 100px

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:grid-auto-rows。

請參閱 CodePen 上 Rachel Andrew (@rachelandrew) 的 Pen Grid Container:grid-auto-rows。

使用具有自動放置功能的網格

創建一個網格(並允許瀏覽器自動放置項目)在您可以實現的有用模式方面讓您有很長的路要走。 我們還沒有考慮在網格上放置項目,但是許多使用 Grid 的佈局不做任何放置。 他們只是依賴於將項目按源順序排列——每個網格單元中都有一個。

如果您是 CSS Grid 的新手,那麼使用不同的軌道大小並查看項目如何將自己放置到您創建的單元格中是一個很好的開始方式。

  • 第 1 部分:創建網格容器
  • 第 2 部分:網格線
  • 第 3 部分:網格模板區域