CSS 網格級別 2:子網格來了

已發表: 2022-03-10
快速總結↬ CSS Grid Level 2 已經在製定過程中,而這一級別規範的主要特點是為我們帶來了 subgrid。 在本文中,Rachel Andrew 解釋了這些新功能。

從 CSS Grid Layout 登陸我們的大多數瀏覽器到現在,我們已經過去了一年多的時間,而且 CSS 工作組已經在著手製定規範的第 2 級。 在本文中,我將解釋目前該規範的工作和編輯草案的一部分。 請注意,此處的所有內容都可能會發生變化,並且目前在瀏覽器中均不適用。 以此作為對過程的一瞥,我相信隨著我們開始看到實現初具規模,我會寫出更多實用的文章。

CSS 規範級別

我們目前可以在瀏覽器中使用的 CSS Grid 特性來自於 CSS Grid 規範的 Level 1。 CSS 的各個部分被分解為模塊; 這種模塊化發生在 CSS 從 CSS 2.1 開始時,這就是為什麼你有時會聽到人們談論 CSS3。 實際上,沒有 CSS3。 取而代之的是一組模塊,其中包含了 CSS2.1 規範中已經包含的所有內容。 CSS2.1 中存在的任何 CSS 都成為了 Level 3 模塊的一部分,因此,我們有 CSS Selectors Level 3,因為選擇器存在於 CSS2.1 中。

不屬於 CSS2.1 的新 CSS 功能(例如 CSS 網格佈局)從 Level 1 開始。CSS Grid Level 1 規範本質上是 Grid 的第一個版本。 一旦規範級別進入候選推薦狀態,就不會添加主要的新功能。 這意味著瀏覽器和其他用戶代理可以實現該規範,並且可以成為 W3C 推薦。 如果要設計新功能,它們將出現在規範的新級別中。 我們在這一點上使用 CSS 網格佈局。 1 級規範在 CR 中,並且已經創建了 2 級規範,以便處理新功能。 如果您想跟進規範討論,我建議您查看編輯草稿,因為這將包含所有最新的編輯。

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

CSS Grid 2 級將包含什麼?

最終,級別 2 規範將包含級別 1 中的所有內容以及一些新功能。 如果您在撰寫本文時查看規範,有一條註釋解釋說,一旦 Level 2 達到 CR,應複製所有 Level 1。

然後我們可以期待找到一些新的特性,並且網格規範的第 2 級就是關於解決 CSS 網格的子網格特性。 此功能已從 Level 1 規範中刪除,以便有時間正確理解 subgrid 的用例,並有更多時間來處理它而不會阻礙 Level 1 的其餘部分。在本文的其餘部分,我將看看當前編輯草稿中詳細介紹的子網格功能。 我們處於該功能的早期階段,但是,這是跟進的最佳時機,並實際幫助塑造規範的開發方式。 我寫這篇文章的目的是解釋一些正在討論的事情,以便您能夠理解並將您的意見帶到討論中。

什麼是子網格?

使用 CSS 網格佈局時,您已經可以嵌套網格。 在下面的示例中,我有一個包含六列軌道和三行軌道的父網格。 我已經在這個網格上從第 2 列到第 6 行以及從第 1 行到第 3 行定位了一個項目。然後我將該項目設置為一個網格容器並定義了列軌道。

 .grid { display: grid; grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: 2fr 1fr 2fr 1fr; }

我們嵌套網格的軌道與父節點上的軌道沒有關係。 這意味著,如果我們希望能夠將嵌套網格的軌道與外部網格上的線對齊,我們必須完成這項工作並使用計算軌道大小的方法來確保所有軌道保持相等。 在上面的示例中,軌道將看起來排成一行,直到將較大尺寸的項目添加到網格的一個單元格(使其占用更多空間)。

帶有顯示線條的 Firefox 網格檢查器的網格
一個小項目意味著軌道看起來好像它們排成一列。 (大預覽)
與第一個示例一樣,除了嵌套網格現在不與外部對齊。
對於一個大項目,我們可以看到軌道沒有對齊。 (大預覽)

對於列,通常可以繞過上述情況,主要是通過限製網格的靈活性。 您可以將fr單位列minmax(0,1fr)以便它們在進行空間分配時忽略項目大小,或者您可以重新使用百分比。 但是,這消除了使用網格的一些好處,並且當涉及到在嵌套網格中排列行時,這些方法將不起作用。

假設我們想要一個卡片佈局,其中各個卡片都有頁眉、正文和頁腳。 我們還希望頁眉和頁腳在卡片上對齊。

 .cards { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-gap: 20px; } .card { display: grid; grid-template-rows: auto 1fr auto; }
一個容器中的三張卡片
一組卡片(大預覽)

只要每個頁眉和頁腳中的內容高度相同,這就會起作用。 如果我們有額外的內容,那麼錯覺就會被打破,頁眉和頁腳不再在行中對齊。

容器中的三張牌,其中一個標頭比其他標高
我們無法讓標題在卡片上對齊。 (大預覽)

創建子網格

我們現在可以看看當前如何指定子網格特徵,以及它如何解決我上面展示的問題。

注意在撰寫本文時,以下代碼均不適用於瀏覽器。 這裡的目的是解釋語法和概念。 最終的規範也可能會從這些細節中改變。 作為參考,我根據 2018 年 6 月 23 日提供的編輯草稿撰寫了這篇文章。

要創建子網格,我們將為grid-template-rowsgrid-template-columns設置一個新值。 這些屬性通常與軌道列表一起使用,它定義了行和列軌道的數量和大小。 但是,在創建子網格時,您不想指定這些軌道。 相反,您使用subgrid值告訴網格這個嵌套網格應該使用它所覆蓋的網格區域跨越的軌道數量和軌道大小。

在下面的代碼中,我有一個包含 6 列軌道和 3 行軌道的父網格。 嵌套網格是該父網格上的一個網格項,從第 2 列到第 6 列,從第 1 行到第 4 行。這就像我們最初的示例一樣,但是,我們現在可以使用子網格。 嵌套subgrid對於grid-template-columnsgrid-template-rows都有一個 subgrid 的值。 這意味著嵌套網格現在有 4 列軌道和 2 行軌道,使用與父節點上定義的軌道相同的大小。

 .grid { display: grid; grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid; }
網格圖
嵌套網格使用父級上定義的軌道。 (大預覽)

這意味著對父級軌道大小的任何更改都將跟隨嵌套網格。 更長的單詞使父網格中的一個軌道更寬會導致嵌套網格中的軌道也變得更寬,所以事情會繼續排列。 這也適用於另一種方式:父網格的軌道可以根據子網格中的內容變得更寬。

一維子網格

您可以在一個維度中有一個子網格,並在另一個維度中指定軌道大小。 在下一個示例中,子網格僅在grid-template-columns上指定。 grid-template-rows屬性具有指定的跟踪列表。 因此,列軌道將保留為我們在上面看到的四個軌道,但行軌道可以單獨定義到父軌道。

 .grid { display: grid; grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: subgrid; grid-template-rows: 10em 5em 200px 200px; }

這意味著子網格的行將嵌套在父網格內,就像今天創建嵌套網格時一樣。 由於我們的嵌套網格跨越父網格的兩行,因此這些行中的一個或兩個都需要擴展以包含子網格的內容,以免導致溢出。

您也可以在一個維度中有一個子網格,而另一個維度使用隱式軌道。 在下面的示例中,我沒有指定任何行軌道,並為grid-auto-rows提供了一個值。 行將以我指定的大小在隱式網格中創建,並且與前面的示例一樣,父級將需要為這些行留出空間或擴展以包含它們。

 .grid { display: grid; grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: subgrid; grid-auto-rows: minmax(200px, auto); }

行號和子網格

如果我們再次看一下我們的第一個示例,我們的子網格的軌道大小由兩個維度的父級決定。 但是,行號在子網格中正常運行。 內聯方向的第一列行是第 1 行,內聯方向遠端的行是第 -1 行。 您不使用父項的行號來引用子網格的行。

 .grid { display: grid; grid-template-columns: 1fr 2fr 1fr 2fr 1fr 2fr; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: subgrid; grid-template-rows: subgrid; } .subitem { grid-column: 2 / 4; grid-row: 2; }
一個網格圖,其中另一個嵌套在裡面
嵌套網格從第 1 行開始編號。(大預覽)

間隙和子網格

子網格將繼承父網格上設置的任何列間距或行間距,但是,這可以被子網格上指定的列間距和行間距推翻。 例如,如果父網格的column-gap設置為 20px,但子網格的column-gap設置為 0,則子網格的網格單元將在每側增加 10px,以將間隙減小到 0,網格線基本上沿著間隙的中間向下延伸。

我們現在可以看到 subgrid 如何幫助我們解決本文開頭的第二個用例,即讓卡片的頁眉和頁腳在卡片上對齊。

 .grid { display: grid; grid-template-columns: 1fr 1fr 1fr; grid-auto-rows: auto 1fr auto; grid-gap: 20px; } .card { grid-row: auto / span 3; /* use three rows of the parent grid */ display: grid; grid-template-rows: subgrid; grid-gap: 0; /* set the gap to 0 on the subgrid so our cards don't have gaps */ }
三張卡片的頁眉和頁腳對齊
卡片內部結構現已排列(大預覽)

線名和子網格

父網格上的任何線名都將傳遞給子網格。 因此,如果我們在父網格上命名線條,我們可以根據這些線條名稱定位項目。

 .grid { display: grid; grid-template-columns: [a] 1fr [b] 2fr [c] 1fr [d] 2fr [e] 1fr [f] 2fr [g]; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: subgrid; grid-template-rows: 10em 5em 200px 200px; } .subitem { grid-column: c / e; }
顯示線名稱適用於網格和子網格的圖表
父項上的行名稱適用於子網格。 (大預覽)

您還可以將線名添加到子網格中,網格線可以有多個線名,因此這些名稱將添加到線中。 要指定行名稱,請在grid-template-columnsgrid-template-rowssubgrid值之後添加這些名稱的列表。 如果我們採用上面的示例並向子網格線添加名稱,那麼子網格中的任何線都會有兩個線名。

 .grid { display: grid; grid-template-columns: [a] 1fr [b] 2fr [c] 1fr [d] 2fr [e] 1fr [f] 2fr [g]; grid-template-rows: auto auto auto; } .item { grid-column: 2 / 6; grid-row: 1 / 3; display: grid; grid-template-columns: subgrid [sub-a] [sub-b] [sub-c] [sub-d] [sub-e]; grid-template-rows: 10em 5em 200px 200px; } .subitem { grid-column: c / e; }
顯示子網格上的線名的圖表被添加到父網格上
子網格上指定的線名稱將添加到父網格的名稱中。 (大預覽)

隱式軌道和子網格

一旦您確定網格的維度是子網格,這將消除在該維度中具有任何其他隱式軌道的能力。 如果您添加更多可以容納的項目,則附加項目將被放置在子網格的最後一個可用軌道中,就像在過大的網格中處理項目一樣。 在子網格中創建的網格區域跨越的軌道多於可用軌道,其最後一行將設置為子網格的最後一行。

然而,如上所述,您可以讓子網格的一維行為方式與普通嵌套網格完全相同,包括隱式軌道。

參與流程

CSS 工作組的工作在 GitHub 上公開進行,就像任何其他開源項目一樣。 這使得跟踪工作變得更容易,因為它是郵件列表中發生的所有事情。 您可以通過在 CSS 工作組 GitHub 存儲庫中搜索標記為 css-grid-2 的問題來查看針對 CSS 網格規範第 2 級提出的問題。 如果您可以為這些問題中的任何一個提供想法或用例,我們將受到歡迎。

人們還要求 CSS Grid Layout 提供其他功能,並且它們沒有被包含在 Level 2 中的事實並不意味著它們沒有被考慮。 您可以看到產品中的功能發布級別,僅僅因為某些功能不是當前衝刺的一部分,並不意味著它永遠不會發生。 開發新的 Web 平台功能往往需要比平均產品發佈時間稍長的時間,但這是一個類似的過程。

這一切需要多長時間?

規範開發和瀏覽器實現是一個有點循環的迭代過程。 在我們看到一些瀏覽器實現之前,並不是需要“完成”規範。 最初的實現很可能落後於特性標誌——就像最初的網格規範一樣。 請留意這些出現,因為一旦有代碼可以使用它,就可以更輕鬆地考慮這些功能!

我希望這次可能即將到來的旅行很有趣。 我很高興 subgrid 功能正在進行中,因為我一直認為它對於 web 的完整網格佈局系統至關重要,請觀看此空間以獲取有關該功能如何進展以及新興瀏覽器實現的更多新聞。