子網格
CSS 網格佈局模組為 grid-template-columns 和 grid-template-rows 包含一個 subgrid 值。本指南詳細介紹了 subgrid 的作用,並給出了一些該功能可以解決的用例和設計模式。
Subgrid 簡介
當你向網格容器新增 display: grid 時,只有直接子元素會成為網格項,然後可以放置在你建立的網格上。這些項的子元素則按正常流顯示。
你可以透過將網格項設定為網格容器來“巢狀”網格。然而,這些網格獨立於父網格和彼此,這意味著它們不會從父網格繼承軌道尺寸。這使得將巢狀的網格項與主網格對齊變得困難。
如果你在 grid-template-columns、grid-template-rows 或兩者上設定了 subgrid 值,巢狀的網格將使用父級上定義的軌道,而不是建立一個新的軌道列表。
例如,如果你使用 grid-template-columns: subgrid 並且巢狀網格跨越父級的三個列軌道,那麼巢狀網格將擁有三個與父網格大小相同的列軌道。雖然間距是繼承的,但可以用不同的 gap 值來覆蓋。可以從父級向子網格傳遞網格線名稱,子網格也可以宣告自己的網格線名稱。
列的 Subgrid
在下面的示例中,網格佈局有九個 1fr 的列軌道和四行至少 100px 高的行。
.item 放置在第 2 到 7 列線和第 2 到 4 行線之間。這個網格項本身透過 display: grid 被指定為一個網格,然後透過為其指定作為子網格的列軌道(grid-template-columns: subgrid)和正常定義的行,被定義為一個子網格。該子網格有五個列軌道,因為它跨越了五個列軌道。
因為 .item 是一個子網格,所以即使 .subitem 不是外部 .grid 的直接子元素,它也可以被放置在那個外部網格上,其列與外部網格的列對齊。行不是子網格,因此其行為與普通巢狀網格一樣。父級上的網格區域會擴充套件到足以容納這個巢狀網格的大小。
<div class="grid">
<div class="item">
<div class="subitem"></div>
</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(4, minmax(100px, auto));
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid;
grid-template-rows: repeat(3, 80px);
}
.subitem {
grid-column: 3 / 6;
grid-row: 1 / 3;
}
注意,在子網格內部,行號會重新開始——在子網格內部,列線 1 是子網格的第一條線。子網格元素不繼承父網格的行號。這意味著你可以安全地佈局一個可能放置在主網格不同位置的元件,同時知道該元件上的行號將始終相同。
行的 Subgrid
此示例使用與上面相同的 HTML,但在這裡,subgrid 被用作 grid-template-rows 的值,並明確定義了列軌道。在這種情況下,列軌道的行為像一個常規的巢狀網格,但行則與 .item 跨越的兩個軌道繫結。
.grid {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(4, minmax(100px, auto));
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: repeat(3, 1fr);
grid-template-rows: subgrid;
}
.subitem {
grid-column: 2 / 4;
grid-row: 1 / 3;
}
兩個維度的 Subgrid
在此示例中,行和列都被定義為子網格,將子網格在兩個維度上都與父網格的軌道繫結。
.grid {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(4, minmax(100px, auto));
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}
.subitem {
grid-column: 3 / 6;
grid-row: 1 / 3;
}
子網格維度中沒有隱式網格
如果你需要自動放置專案並且不知道將有多少專案,建立子網格時要小心,因為它會阻止建立額外的行來容納這些專案。
看下一個示例——它使用了與上面示例中相同的父網格和子網格。子網格內部有十二個專案試圖將自己自動放置到十個網格單元中。由於子網格在兩個維度上都存在,額外的兩個專案沒有地方可去,所以它們進入了網格的最後一個軌道。這是規範中定義的行為。
<div class="grid">
<div class="item">
<div class="subitem">1</div>
<div class="subitem">2</div>
<div class="subitem">3</div>
<div class="subitem">4</div>
<div class="subitem">5</div>
<div class="subitem">6</div>
<div class="subitem">7</div>
<div class="subitem">8</div>
<div class="subitem">9</div>
<div class="subitem">10</div>
<div class="subitem">11</div>
<div class="subitem">12</div>
</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(4, minmax(100px, auto));
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}
透過移除 grid-template-rows 值,可以啟用常規的隱式軌道建立,從而根據需要建立任意多行。這些行將不會與父級的軌道對齊。
<div class="grid">
<div class="item">
<div class="subitem">1</div>
<div class="subitem">2</div>
<div class="subitem">3</div>
<div class="subitem">4</div>
<div class="subitem">5</div>
<div class="subitem">6</div>
<div class="subitem">7</div>
<div class="subitem">8</div>
<div class="subitem">9</div>
<div class="subitem">10</div>
<div class="subitem">11</div>
<div class="subitem">12</div>
</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(4, minmax(100px, auto));
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid;
grid-auto-rows: minmax(100px, auto);
}
間距屬性和 Subgrid
在父級上指定的任何 gap、column-gap 或 row-gap 值都會傳遞到子網格中,從而在軌道之間建立與父級相同的間距。這個預設行為可以透過在子網格容器上應用 gap-* 屬性來覆蓋。
在此示例中,父網格的行和列間距為 20px,而子網格的 row-gap 設定為 0。
<div class="grid">
<div class="item">
<div class="subitem"></div>
<div class="subitem2"></div>
</div>
</div>
.grid {
display: grid;
grid-template-columns: repeat(9, 1fr);
grid-template-rows: repeat(4, minmax(100px, auto));
gap: 20px;
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
row-gap: 0;
}
.subitem {
grid-column: 3 / 6;
grid-row: 1 / 3;
}
.subitem2 {
background-color: rgb(0 0 0 / 0.5);
grid-column: 2;
grid-row: 1;
}
如果你在開發者工具的網格檢查器中檢查這一點,你會注意到子網格線位於間距的中心。將間距設定為 0 的作用類似於對元素應用負外邊距,將間距的空間還給專案。

命名網格線
使用 CSS 網格時,你可以為網格上的線命名,然後根據這些名稱而不是行號來定位專案。父網格上的線名稱會傳遞到子網格中,你可以使用它們來放置專案。在下面的示例中,父級的命名線 col-start 和 col-end 被用來放置子專案。
<div class="grid">
<div class="item">
<div class="subitem"></div>
</div>
</div>
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr [col-start] 1fr 1fr 1fr [col-end] 1fr 1fr 1fr;
grid-template-rows: repeat(4, minmax(100px, auto));
gap: 20px;
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid;
grid-template-rows: subgrid;
}
.subitem {
grid-column: col-start / col-end;
grid-row: 1 / 3;
}
你也可以在子網格上指定線名稱。這是透過在 subgrid 關鍵字後新增一個用方括號括起來的線名稱列表來實現的。例如,如果你的子網格中有四條線,要為它們全部命名,你可以使用語法 grid-template-columns: subgrid [line1] [line2] [line3] [line4]
在子網格上指定的線會新增到在父級上指定的任何線之上,因此你可以使用其中一個或兩者。在此示例中,一個專案使用父級線放置在下方,另一個使用子網格線放置。
<div class="grid">
<div class="item">
<div class="subitem"></div>
<div class="subitem2"></div>
</div>
</div>
.grid {
display: grid;
grid-template-columns: 1fr 1fr 1fr [col-start] 1fr 1fr 1fr [col-end] 1fr 1fr 1fr;
grid-template-rows: repeat(4, minmax(100px, auto));
gap: 20px;
}
.item {
display: grid;
grid-column: 2 / 7;
grid-row: 2 / 4;
grid-template-columns: subgrid [sub-a] [sub-b] [sub-c] [sub-d] [sub-e] [sub-f];
grid-template-rows: subgrid;
}
.subitem {
grid-column: col-start / col-end;
grid-row: 1 / 3;
}
.subitem2 {
background-color: rgb(0 0 0 / 0.5);
grid-column: sub-b / sub-d;
grid-row: 1;
}
使用 Subgrid
子網格的行為與任何巢狀網格非常相似;唯一的區別是子網格的軌道尺寸是在父網格上設定的。然而,與任何巢狀網格一樣,子網格中內容的大小可以改變軌道尺寸,前提是使用了允許內容影響尺寸的軌道尺寸設定方法。在這種情況下,自動調整大小的行軌道將增長以適應主網格和子網格中的內容。
由於 subgrid 值的行為與常規巢狀網格非常相似,因此在兩者之間切換很容易。例如,如果你發現你需要一個用於行的隱式網格,你需要移除 grid-template-rows 的 subgrid 值,並可能為 grid-auto-rows 提供一個值來控制隱式軌道的尺寸。
規範
| 規範 |
|---|
| CSS 網格佈局模組 Level 2 # subgrids |
瀏覽器相容性
載入中…
另見
- 影片:使用 subgrid 佈局表單 (2019)
- 影片:不要再等了,用 subgrid 獲得更好的卡片佈局 (2019)
- 影片:你好 subgrid!CSSConf.eu (2019) 演講