深入研究顯示屬性:網格一直向下

已發表: 2022-03-10
快速總結↬繼續介紹 CSS 中的display屬性系列,這次 Rachel Andrew 將看看當您使用 grid 作為 display 的值時會發生什麼,並添加了有關 subgrid 如何更改該行為的信息。

今天,我們將看看當我們使用display: grid時會發生什麼,以及我們如何使用grid-template-columnsgrid-template-rows的新 subgrid 值來允許網格一直向下通過我們的標記, 它們相互關聯。

本文是研究 CSS display屬性各個方面的系列文章的一部分,是前兩篇文章的後續文章:

  1. display的兩個值
  2. 盒子生成
  3. 網格一直向下

當我們創建一個網格容器時會發生什麼?

使用display: grid打開 CSS 網格佈局。 如果你看過本系列的第一篇文章,你就會知道這個單值屬性的真正含義是display: block grid 。 我們得到一個塊級框,它被定義為一個網格容器,其直接子項是網格項並參與網格佈局。

如果您查看顯示規範,您將在表中看到它定義了display的所有不同值。 網格容器一詞與網格規範中的網格容器定義相關聯。 因此,要找出這實際上意味著什麼,我們需要去那裡看看。 當我們這樣做時,我們對網格容器的行為得到了一些有用的說明。

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

網格容器被稱為建立一個類似於塊格式化上下文(BFC)的網格格式化上下文。 我已經為塊格式化上下文寫了一個詳盡的指南。 在那篇文章中,您將發現關於 BFC 的兩件事與網格格式化上下文相同。 浮動不會侵入網格容器,容器上的邊距不會與內容的邊距一起折疊。

然而,只有當我們進入網格容器時,它們才會有所不同。 網格容器的子項,不參與塊和內聯佈局,它們是網格項,因此參與網格佈局。 這意味著我們在塊和內聯佈局中習慣的一些事情並不適用。

如果佈局中的任何項目被浮動或清除,一旦項目成為網格項目, floatclear屬性將不起作用。 vertical-align屬性無效,不能使用::first-letter::first-line偽元素。

項目不能同時浮動和網格項目這一事實有助於創建後備。 當為不支持使用浮動網格的瀏覽器創建後備時(當支持網格時),您不需要做任何特殊的事情:浮動被覆蓋。

我在關於支持沒有網格的瀏覽器的文章中概述了這種方法。 在某些情況下,行為會出現問題,儘管這些問題可以通過使用 CSS 的另一部分來解決,如這篇文章中描述的關於網格和浮動的問題,“編輯佈局、排除和 CSS 網格”。

話雖如此,如果我們只是將display的值更改為grid ,我們不會看到佈局有太大的不同。 直接子項是網格項,但是,默認情況下,我們以單列網格結束。 網格總是有一列一行。 執行此操作後我們可以看到的其餘行是隱式行,即為保存內容而創建的行。

一組卡片在單列中一張在另一張下方。
當我們創建一個沒有列的網格容器時,我們得到一個單列網格。 (大預覽)

我們可以通過給屬性grid-template-columns一個值來開始形成看起來更像網格的東西。 該屬性將軌道列表作為值; 如果我給它三個 1fr 軌道,我們現在會發現自己有一個三列網格,並且使用gap屬性可以讓我在這些卡片之間留出間距。

我們現在有一些看起來像網格的東西:

三列兩行的卡片
我們定義了一些列軌道和間隙以獲得明顯的網格佈局(大預覽)

我們示例中的每個網格項都有自己的子項。 卡片有頁眉和頁腳以及卡片主要內容的區域。 這些孩子是網格項目,但他們的孩子已經回到塊和內聯佈局。 頁眉、內容區域和頁腳不做任何類似網格的事情。 這是因為當我們將display的值更改為grid時,它不會繼承,而是只有子項成為網格項; 他們的孩子返回到塊佈局。

嵌套網格

如果一張卡片的內容比其他卡片多,則該行中的卡片會變得更高。 網格項目的align-items的初始值為stretch 。 我們的卡片可以伸展到全高。 然而,裡面的項目是正常的塊和內聯流,所以它們不會神奇地伸展來填滿卡片。 (這就是為什麼在上圖中您可以看到內容較少的卡片在底部有一個間隙。)

如果我們想要它們(為了使頁腳始終位於底部),我們也可以將網格項設為網格。 在這種情況下,我們只需要一個單列網格。 然後,我們可以定義行軌道,給具有類別內容的div所在的區域,軌道大小為1fr 。 這會導致它佔用容器中的所有可用空間,並將頁腳推到卡片的底部。

請參閱 Rachel Andrew 的 Pen [顯示:子網格不是我們想要的](https://codepen.io/rachelandrew/pen/PvQzeG)。

請參閱數位屏:Rachel Andrew 不是我們想要的子網格。

您可以根據需要盡可能多地進行網格嵌套。 我真的不認為它是嵌套,因為我們沒有在這裡創建嵌套表,而且我們通常使用已經存在的結構化 HTML 元素。 我們只是一次將display的值更改為最適合該元素的子元素的值。 這可能是彈性佈局或網格佈局,但最常見的是塊佈局和內聯佈局。 在這種情況下,我們不需要做任何事情,因為這是默認情況下發生的。

對齊頁眉和頁腳

正如我們現在看到的,如果我們想要將一組卡片佈置在網格上,並且我們希望它們顯示的高度與最高的卡片一樣高,並且我們希望頁腳被推到卡片的底部,我們只需要很少的 CSS . 上述示例的佈局 CSS 如下:

 .cards { display: grid; gap: 20px; grid-template-columns: 1fr 1fr 1fr; } article { display: grid; grid-template-rows: auto 1fr auto; row-gap: 20px; }

如果我們希望頁眉和頁腳的背景顏色對齊怎麼辦? 每張卡片都是一個網格項目,但頁眉和頁腳位於項目的網格中。 它們彼此沒有關係,因此我們無法排列它們。 如果我們能以某種方式通過孩子繼承網格,那就太好了。

如果我們可以在具有三行的父級上定義一個網格,然後將卡片放置在這三行中,並讓頁眉、內容和頁腳分別位於其中一行。 這樣,每個標題將位於同一行,因此如果一個標題變高,則整行都會變高。

我們今天在瀏覽器中沒有很好的解決方案,但它正在開發中。 CSS Grid Layout Level 2 的 subgrid 特性將啟用這種精確的模式。 您將能夠在父元素上創建一個網格,然後有選擇地選擇行和/或列來使用該網格,而不是在完全獨立於該網格的child元素上定義一個新網格。

請注意,以下示例僅在撰寫 Firefox Nightly 時有效。 grid-template-columnsgrid-template-rows的 subgrid 值是CSS 網格規範第 2 級的新特性和一部分。 要試用此功能,請下載 Firefox Nightly 的副本。

您可以在下面的圖片中看到它是如何工作的。 在第一張圖片中,我在父級上創建了三行軌道,並將卡片跨越它們。 隨著 Firefox Grid Inspector 突出顯示網格,您可以看到父級的行與子級使用的行無關。

覆蓋了 Firefox Grid Inspector 軌道的三列網格的圖像。
使用 Firefox Grid Inspector 檢查網格顯示元素未顯示在父元素的軌道中。 (大預覽)

如果我沒有在子級上定義三行,而是使用grid-template-rows的 subgrid 值,那麼卡片現在在父級上使用這些行。 您可以看到兩者現在是如何對齊的,因此頁眉和頁腳也對齊:

三列網格的圖像,卡片內的所有元素對齊。
使用 subgrid 卡片的每個部分進入自己的軌道(大預覽)

我們在這裡對 subgrid 所做的並不是display的新值。 作為子網格的項目本身就是一個網格容器,因為我們在其上設置了display: grid 。 網格項的行為與通常的網格項一樣。 這是常規的網格佈局 - 與原始嵌套網格沒有什麼不同,只是它使用父級的軌道(而不是具有自己的行軌道大小的項目)。

 .cards { display: grid; gap: 20px; grid-template-columns: 1fr 1fr 1fr; grid-template-rows: repeat(2,auto 1fr auto); } article { grid-row-end: span 3; display: grid; grid-template-rows: subgrid; }

這是子網格的好處; 如果您已經知道如何使用網格佈局,則無需學習太多東西。 您可以在我之前在 Smashing Magazine 上發表的文章“CSS Grid Level 2: Here Comes Subgrid”中閱讀其他詳細信息。

昨天(2019 年 5 月23日),subgrid 登陸了 Firefox Nightly,所以我們有了grid-template-columnsgrid-template-rows的 subgrid 值的可測試實現。 請務必獲取 Nightly 的副本並嘗試一下。 使用 Nightly 的副本,您可以看到在此 CodePen 中運行的最後一個示例:

請參閱數位屏:Rachel Andrew 不是我們想要的子網格。

請參閱數位屏:Rachel Andrew 不是我們想要的子網格。

看看您是否可以想出通過子網格功能解決的其他用例,或者您認為缺少的東西。 雖然某項功能僅在 Nightly 瀏覽器中可用,但如果發現某些問題,則可以對規范進行更改。 因此,請為您未來的網絡開發自己提供幫助,並嘗試這樣的功能,以便您可以為網絡平台做出貢獻並使事情變得更好。

如果您認為您在 Firefox 實現中發現了錯誤,您可以查看 Bugzilla 上的主要實現錯誤,該錯誤鏈接到依賴部分中的相關問題。 如果您看不到您的問題,請盡可能創建一個簡單的簡化測試用例並提出錯誤。 如果你認為 subgrid 應該做一些事情來解決一個用例,而這在規範中沒有詳細說明,你可以在 CSS 工作組 GitHub 上提出一個問題,以獲得潛在的增強。

怎麼樣display: contents

如果您一直在關注,您可能會認為display: contents (如上一篇關於display的文章中所述)可能會解決 subgrid 試圖解決的問題 - 允許間接子級參與網格佈局的問題。 事實並非如此,我們的卡片示例是展示差異的完美方式。

如果我們不使用display: grid使我們的卡片成為網格佈局,而是使用display: contents刪除該框,我們將在下一個 CodePen 中得到這個結果。 (嘗試從.card的規則中刪除display: contents行以查看差異。)

請參閱數位屏:Rachel Andrew 不是我們想要的子網格。

請參閱數位屏:Rachel Andrew 不是我們想要的子網格。

在此示例中,卡片的框已被移除,因此頁眉、內容和頁腳直接參與網格佈局並在網格中自動放置。 這根本不是我們想要的! 處理完我上一篇文章中提到的瀏覽器的可訪問性問題後,顯示的contents值將非常有用,但是,它解決了與我們正在探索的問題不同的問題。

更多閱讀和示例

我一直在創建一些示例和演示來幫助每個人理解 subgrid。 您可以在下面的鏈接中嘗試這些:

  • CSS 網格 2 級示例
  • CSS 網格級別 2:子網格來了
  • 網格一直向下(演示文稿)
  • 子網格的 MDN 文檔