CSS 網格佈局

CSS 網格佈局是一種用於 Web 的二維佈局系統。它允許您將內容組織成行和列,並提供了許多功能來簡化複雜佈局的建立。本文將解釋您開始使用網格佈局所需瞭解的所有內容。

預備知識 使用 HTML 構造內容CSS 樣式基礎文字和字型樣式基礎,熟悉CSS 佈局基本概念
學習成果
  • 瞭解 CSS 網格的目的——以二維方式靈活地佈局一組塊級或行內元素。
  • 瞭解網格術語——行、列、間隙和槽溝。
  • 瞭解 display: grid 預設提供的內容。
  • 定義網格行、列和間隙。
  • 在網格上定位元素。

什麼是網格佈局?

網格是一系列水平線和垂直線的集合,它們建立了一個模式,我們可以根據該模式排列我們的設計元素。它們幫助我們建立佈局,使我們的元素在頁面之間移動時不會跳動或改變寬度,從而為我們的網站提供更大的一致性。

網格通常有,以及每行和每列之間的間隙。這些間隙通常被稱為槽溝

CSS grid with parts labelled as rows, columns and gutters. Rows are the horizontal segments of the grid and Columns are the vertical segments of the grid. The space between two rows is called as 'row gutter' and the space between 2 columns is called as 'column gutter'.

在 CSS 中建立網格

確定設計所需的網格後,您可以使用 CSS 網格佈局來建立它。我們首先將瞭解網格佈局的基本功能,然後探討如何為您的專案建立一個簡單的網格系統。下面的影片提供了使用 CSS 網格的良好視覺解釋

定義網格

讓我們試試網格佈局,這裡有一個帶容器的示例,其中包含一些子項。預設情況下,這些項以正常流顯示,導致它們一個接一個地出現。

html
<div class="container">
  <div>One</div>
  <div>Two</div>
  <div>Three</div>
  <div>Four</div>
  <div>Five</div>
  <div>Six</div>
  <div>Seven</div>
</div>
css
body {
  font-family: sans-serif;
}
.container > div {
  border-radius: 5px;
  padding: 10px;
  background-color: rgb(207 232 220);
  border: 2px solid rgb(79 185 227);
}

與定義 flexbox 類似,您透過將 display 屬性的值設定為 grid 來定義網格佈局。與 flexbox 的情況一樣,display: grid 屬性將容器的所有直接子項轉換為網格項。我們已將以下 CSS 新增到檔案中

css
.container {
  display: grid;
}

與 flexbox 不同,這些項不會立即看起來有所不同。宣告 display: grid 會為您提供一個一列網格,因此您的項將像在正常流中一樣繼續一個接一個地顯示。

為了看到更像網格的東西,我們需要向網格新增一些列。讓我們新增三列 200 畫素的列。您可以使用任何長度單位或百分比來建立這些列軌道。

css
.container {
  display: grid;
  grid-template-columns: 200px 200px 200px;
}

您應該會看到這些項已重新排列,以便網格的每個單元格中都有一個。

使用 fr 單位的靈活網格

除了使用長度和百分比建立網格之外,我們還可以使用 frfr 單位表示網格容器中可用空間的一個分數,用於靈活調整網格行和列的大小。

在這裡,我們將軌道列表更改為以下定義,建立三個 1fr 軌道

css
.container {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
}

您現在擁有靈活的軌道。fr 單位按比例分配空間,因此您可以為您的軌道指定不同的正值。將您的軌道列表更改為以下定義,建立一個 2fr 軌道和兩個 1fr 軌道

css
.container {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
}

第一個軌道獲得可用空間的 2fr,而其他兩個軌道獲得 1fr,使第一個軌道更大。您可以將 fr 單位與固定長度單位混合使用。在這種情況下,首先用完固定軌道所需的空間,然後將剩餘空間分配給其他軌道。

注意: fr 單位分配的是可用空間,而不是所有空間。因此,如果您的一個軌道內部有較大的內容,則可共享的可用空間會更少。

軌道之間的間隙

為了在軌道之間建立間隙,我們使用以下屬性

在這裡,我們新增 gap 屬性以建立軌道之間的間隙,值為 20px

css
.container {
  display: grid;
  grid-template-columns: 2fr 1fr 1fr;
  gap: 20px;
}

這些間隙可以是任何長度單位或百分比,但不能是 fr 單位。

重複軌道列表

您可以使用 CSS repeat() 函式重複您的整個軌道列表或僅其一部分。在這裡,我們將軌道列表更改為以下內容

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 20px;
}

您現在將得到三個 1fr 軌道,就像以前一樣。傳遞給 repeat() 函式的第一個值指定您希望列表重複的次數,而第二個值是一個軌道列表,可以是您希望重複的一個或多個軌道。

隱式網格和顯式網格

到目前為止,我們只指定了列軌道,但會自動建立行以容納內容。這個概念突出了顯式網格和隱式網格之間的區別。以下是關於這兩種網格之間區別的更多資訊

  • 顯式網格使用 grid-template-columnsgrid-template-rows 建立。
  • 當內容放置在該網格之外時(例如,透過繪製額外的網格線放置到行中),隱式網格會擴充套件已定義的顯式網格。

預設情況下,隱式網格中建立的軌道是 auto 大小,這通常意味著它們足夠大以包含其內容。如果您希望為隱式網格軌道指定大小,可以使用 grid-auto-rowsgrid-auto-columns 屬性。如果將 grid-auto-rows 和值 100px 新增到 CSS 中,您會看到那些建立的行現在高 100 畫素。

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: 100px;
  gap: 20px;
}

minmax() 函式

如果我們在這些 100 畫素高的軌道中新增高於 100 畫素的內容,那麼這些軌道將不會非常有用,在這種情況下會導致溢位。最好讓軌道至少高 100 畫素,並且如果新增更多內容仍然可以擴充套件。關於 Web 的一個相當基本的事實是,您永遠不知道某個東西會有多高——額外的內容或更大的字型大小可能會導致在每個維度都試圖做到畫素級完美的設計出現問題。

minmax() 函式允許我們為軌道設定最小和最大尺寸,例如 minmax(100px, auto)。最小尺寸為 100 畫素,但最大尺寸為 auto,它將擴充套件以適應更多內容。在這裡,我們將 grid-auto-rows 更改為使用 minmax()

css
.container {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-auto-rows: minmax(50px, auto);
  gap: 20px;
}

如果您新增額外內容,您會看到軌道會擴充套件以適應內容。請注意,擴充套件發生在行中。

儘可能多的列

我們可以結合我們所學的關於軌道列表、重複符號和 minmax() 的一些知識來建立有用的模式。有時,能夠讓網格建立儘可能多的列以適應容器是很有幫助的。我們透過使用 repeat() 函式設定 grid-template-columns 的值來實現這一點,但不是傳入數字,而是傳入關鍵字 auto-fit。對於函式的第二個引數,我們使用 minmax(),其最小值為我們想要的最小軌道大小,最大值為 1fr

css
.container {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
  grid-auto-rows: minmax(50px, auto);
  gap: 20px;
}

這之所以有效,是因為網格會建立儘可能多的 230 畫素列以適應容器,然後將剩餘空間分配給所有列。最大值是 1fr,我們已經知道,它在軌道之間均勻分配空間。

基於線的放置

現在我們從建立網格轉到在網格上放置內容。我們的網格總是有線——這些線從 1 開始編號,並與文件的書寫模式相關。例如,在英語(從左到右書寫)中,列線 1 將在網格的左側,行線 1 在頂部,而在阿拉伯語(從右到左書寫)中,列線 1 將在右側。

為了沿這些線定位專案,我們可以指定專案應放置的網格區域的起始線和結束線。我們可以使用以下四個屬性來完成此操作

這些屬性接受行號作為它們的值,因此我們可以指定一個專案應該從第 1 行開始並在第 3 行結束,例如。另外,您還可以使用速記屬性,允許您同時指定起始線和結束線,用正斜槓 / 分隔

  • grid-columngrid-column-startgrid-column-end 的簡寫
  • grid-rowgrid-row-startgrid-row-end 的簡寫
html
<div class="container">
  <header>Header</header>
  <main>
    <h1>Main</h1>
    <p>Main content…</p>
  </main>
  <aside>
    <h2>Aside</h2>
    <p>Related content</p>
  </aside>
  <footer>footer</footer>
</div>
css
.container {
  font-family: sans-serif;
  display: grid;
  grid-template-columns: 1fr 3fr;
  gap: 20px;
}
header,
footer {
  border-radius: 5px;
  padding: 10px;
  background-color: rebeccapurple;
  color: whitesmoke;
  text-align: center;
}
aside {
  border-right: 1px solid rebeccapurple;
}

在沒有定義位置的情況下,您可以看到自動放置將每個專案放置在網格中的自己的單元格中。<header> 佔據了 1fr (四分之一),<main> 佔據了 3fr (四分之三)。

讓我們使用網格線排列我們網站的所有元素。將以下規則新增到 CSS 的底部

css
header {
  grid-column: 1 / 3;
  grid-row: 1;
}
main {
  grid-column: 2;
  grid-row: 2;
}
aside {
  grid-column: 1;
  grid-row: 2;
}
footer {
  grid-column: 1 / 3;
  grid-row: 3;
}

現在 <header><footer> 設定為 1 / 3,這意味著從第 1 行開始,到第 3 行結束。

注意:您還可以使用值 -1 來定位結束列或行線,然後使用負值從末尾向內計數。另請注意,行始終從顯式網格的邊緣開始計數,而不是隱式網格

使用 grid-template-areas 進行定位

另一種在網格上排列專案的方法是使用 grid-template-areas 屬性併為設計的各個元素命名。

css
.container {
  display: grid;
  grid-template-areas:
    "header header"
    "sidebar content"
    "footer footer";
  grid-template-columns: 1fr 3fr;
  gap: 20px;
}
header {
  grid-area: header;
}
main {
  grid-area: content;
}
aside {
  grid-area: sidebar;
}
footer {
  grid-area: footer;
}

在這裡,我們使用 grid-template-areas 屬性來定義 3 行的佈局方式。第一行值為 header header,第二行值為 sidebar content,第三行值為 footer footer。然後我們使用 grid-area 屬性來定義元素在 grid-template-areas 中的位置。

grid-template-areas 的規則如下

  • 您需要填充網格的每個單元格。
  • 要跨越兩個單元格,請重複名稱。
  • 要留空單元格,請使用 .(句點)。
  • 區域必須是矩形——例如,您不能有 L 形區域。
  • 區域不能在不同位置重複。

您可以調整我們的佈局,將頁尾只放在文章下方,並將側邊欄向下延伸。這是一種非常好的描述佈局的方式,因為只需檢視 CSS 即可清楚地瞭解發生了什麼。

巢狀網格和子網格

可以在另一個網格中巢狀網格,建立 “子網格”。您可以透過在父網格中的專案上設定 display: grid 屬性來實現此目的。

讓我們透過新增文章容器並使用巢狀網格來控制多篇文章的佈局來擴充套件前面的示例。雖然我們在巢狀網格中只使用一列,但我們可以使用 grid-template-rows 屬性將行定義為按 4:3:3 的比例分割。這種方法允許我們建立一個佈局,其中頁面頂部的一篇文章具有大的顯示,而其他文章具有較小的預覽式佈局。

css
main {
  grid-area: content;
  display: grid;
  grid-template-rows: 4fr 3fr 3fr;
  gap: inherit;
}
article {
  padding: 10px;
  border: 2px solid rebeccapurple;
  border-radius: 5px;
}

為了更輕鬆地在巢狀網格中使用佈局,您可以在 grid-template-rowsgrid-template-columns 屬性上使用 subgrid。這允許您利用父網格中定義的軌道。

在下面的示例中,我們使用基於線的定位,使巢狀網格能夠跨越父網格的多個列和行。我們添加了 subgrid 來繼承父網格的列軌道,同時在巢狀網格中為行添加了不同的佈局。

css
.container {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-template-rows: repeat(1, 1fr);
  gap: 10px;
}
.subgrid {
  grid-column: 1 / 4;
  grid-row: 2 / 4;
  display: grid;
  gap: inherit;
  grid-template-columns: subgrid;
  grid-template-rows: 2fr 1fr;
}

網格框架

有許多網格框架可用,提供 12 或 16 列網格,以幫助您佈局內容。好訊息是,您可能不需要任何第三方框架來幫助您建立基於網格的佈局——網格功能已包含在規範中,並受到大多數現代瀏覽器的支援。

這有一個定義了 12 列網格的容器,使用 grid-template-columns: repeat(12, 1fr);,以及我們在前兩個示例中使用的相同標記。我們現在可以使用基於線的定位將內容放置在 12 列網格上。

css
.container {
  font-family: sans-serif;
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: 20px;
}
header {
  grid-column: 1 / 13;
  grid-row: 1;
}
main {
  grid-column: 4 / 13;
  grid-row: 2;
}
aside {
  grid-column: 1 / 4;
  grid-row: 2;
}
footer {
  grid-column: 1 / 13;
  grid-row: 3;
}

如果您使用 Firefox 網格檢查器在您的設計上疊加網格線,您可以看到我們的 12 列網格是如何工作的。

A 12 column grid overlaid on our design.

總結

在本概述中,我們遍歷了 CSS 網格佈局的主要功能。您應該能夠開始在您的設計中使用它。

在下一篇文章中,我們將為您提供一些測試,您可以使用它們來檢查您對所有這些資訊的理解和掌握程度。

另見

CSS 網格佈局

主要的 CSS 網格佈局模組頁面,包含許多其他資源

CSS 網格完整指南

CSS-Tricks 上的視覺指南 (2023)。

Grid Garden

一個教育遊戲,可在 cssgridgarden.com 上學習和更好地理解網格基礎知識。