CSS 巢狀

我們最喜愛的 CSS 前置處理器功能之一現在已內建於語言中:巢狀樣式規則。

Adam Argyle
Adam Argyle

在巢狀結構之前,每個選取器都必須明確宣告,且彼此分開。這會導致重複、大量的樣式表單和零散的撰寫體驗。

之前
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

巢狀後,您可以繼續使用選取器,並將相關樣式規則分組。

使用後
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

在瀏覽器中試試這個方法

巢狀結構可協助開發人員減少重複選取器的需求,同時為相關元素共同定位樣式規則。這也能協助樣式與指定的 HTML 相符。如果先前範例中的 .nesting 元件已從專案中移除,您可以刪除整個群組,而不需要在檔案中搜尋相關的選取器例項。

巢狀結構可協助您完成以下工作: - 組織化 - 縮減檔案大小 - 重構

巢狀結構可在 Chrome 112 以上版本使用,也可以在 Safari 技術預覽版 162 中試用

CSS 巢狀結構入門

在本文的其餘部分中,我們會使用以下示範沙箱,協助您以視覺化方式查看選項。在這個預設狀態下,系統不會選取任何項目,且所有項目都會顯示。您可以選取各種形狀和大小,練習語法並瞭解其運作方式。

彩色格狀圖片,包含大小圓形、三角形和正方形。

沙箱內有圓形、三角形和正方形。有些是小型、中型或大型。其他顏色則是藍色、粉紅色或紫色。這些元素都位於 .demo 包含元素內。以下是您要指定的 HTML 元素預覽畫面。

<div class="demo">
  <div class="sm triangle pink"></div>
  <div class="sm triangle blue"></div>
  <div class="square blue"></div>
  <div class="sm square pink"></div>
  <div class="sm square blue"></div>
  <div class="circle pink"></div>
  …
</div>

巢狀結構範例

CSS 巢狀結構可讓您在其他選取器的內容中為元素定義樣式。

.parent {
  color: blue;

  .child {
    color: red;
  }
}

在本範例中,.child 類別選取器會嵌套在 .parent 類別選取器中。也就是說,巢狀 .child 選取器只會套用至屬於 .parent 類別元素的子項元素。

這個範例也可以使用 & 符號編寫,以明確表示應放置父類別的位置。

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

這兩個範例在功能上是等效的,而您有這些選項的原因,將在本文中進一步探討更進階的範例時會變得更加明確。

選取圓圈

在這個第一個範例中,您需要新增樣式,只淡出及模糊處理示範中的圓形。

不巢套的 CSS 目前如下:

.demo .circle {
  opacity: .25;
  filter: blur(25px);
}

巢狀有兩種有效方式:

/* & is explicitly placed in front of .circle */
.demo {
  & .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

/* & + " " space is added for you */
.demo {
  .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

結果.demo 中所有具有 .circle 類別的元素都會模糊處理,幾乎看不見:

色彩繽紛的形狀格線不再有圓形,但在背景中會顯示非常淡的圓形。
試用示範版

選取任意三角形和正方形

這項工作需要選取多個巢狀元素,也稱為群組選取器

不使用巢狀結構,CSS 目前有兩種方法:

.demo .triangle,
.demo .square {
  opacity: .25;
  filter: blur(25px);
}

或使用 :is()

/* grouped with :is() */
.demo :is(.triangle, .square) {
  opacity: .25;
  filter: blur(25px);
}

巢狀時,有兩種有效方法:

.demo {
  & .triangle,
  & .square {
    opacity: .25;
    filter: blur(25px);
  }
}

.demo {
  .triangle, .square {
    opacity: .25;
    filter: blur(25px);
  }
}

結果.demo 中只剩下 .circle 元素:

彩色形狀的格線只剩下圓形,所有其他形狀幾乎都看不見。
試用示範版

選取大型三角形和圓形

這項任務需要複合選取器,元素必須同時具備兩個類別,才能選取。

不使用巢狀結構的 CSS 目前如下:

.demo .lg.triangle,
.demo .lg.square {
  opacity: .25;
  filter: blur(25px);
}

.demo .lg:is(.triangle, .circle) {
  opacity: .25;
  filter: blur(25px);
}

巢狀時,有兩種有效方法:

.demo {
  .lg.triangle,
  .lg.circle {
    opacity: .25;
    filter: blur(25px);
  }
}

.demo {
  .lg {
    &.triangle,
    &.circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

結果:所有大型三角形和圓形都會隱藏在 .demo 中:

色彩繽紛的格線只會顯示小型和中型形狀。
試用示範版
使用複合選取器和巢狀結構的專家提示

& 符號在這裡很有用,因為它會明確顯示如何連結巢狀的選取器。請參考以下範例:

.demo {
  .lg {
    .triangle,
    .circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

雖然這是有效的巢狀方式,但結果不會符合您預期的元素。原因是如果沒有 & 指定 .lg.triangle, .lg.circle 合併後的預期結果,實際結果將會是 .lg .triangle, .lg .circle; 子系選取器

選取粉紅色以外的所有形狀

這項工作需要否定功能式擬造類別,其中元素不得具有指定的選取器。

不巢套的 CSS 目前如下:

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

巢狀時,有兩種有效方式:

.demo {
  :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

.demo {
  & :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

結果:所有非粉紅色的形狀都會隱藏在 .demo 中:

原本色彩繽紛的格狀圖現在變成單色,只顯示粉紅色圖形。
試用示範版
& 的精確度和彈性

假設您想使用 :not() 選取器指定 .demo& 為必填

.demo {
  &:not() {
    ...
  }
}

這個方法會將 .demo:not() 組合成 .demo:not(),而先前的範例則需要 .demo :not()。如要巢狀排列 :hover 互動,這項提醒就非常重要。

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

更多巢狀結構範例

巢狀 CSS 規格包含更多範例。如果您想透過範例進一步瞭解語法,這裡提供多種有效和無效的範例。

接下來的幾個範例將簡要介紹 CSS 巢狀功能,協助您瞭解這項功能的廣泛應用。

巢狀 @media

移動到樣式表的不同區域,找出用於修改選取器及其樣式的媒體查詢條件,可能會讓您分心。您可以直接在內容中巢狀條件,因此不必再分心處理。

為方便使用語法,如果巢狀媒體查詢只修改目前選取器內容的樣式,則可使用最少的語法。

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

您也可以明確使用 &

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    &.large {
      font-size: 1.25rem;
    }
  }
}

這個範例會顯示使用 & 的展開語法,同時指定 .large 資訊卡,以示範其他巢狀功能仍可正常運作。

進一步瞭解巢狀 @rules

隨處巢狀

到目前為止,所有示例都會繼續或附加至先前的上下文。您可以視需要完全變更或重新排列內容。

.card {
  .featured & {
    /* .featured .card */
  }
}

& 符號代表對選取器物件 (而非字串) 的參照,可放置在巢狀選取器的任何位置。甚至可以多次放置:

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

雖然這個範例看起來沒什麼用處,但在某些情況下,重複選取器內容會很方便。

無效的巢狀結構範例

在某些巢狀語法情境中,如果您在預處理器中巢狀,可能會發現語法無效。

巢狀結構和串連

許多 CSS 類別命名慣例都依賴巢狀結構,以便將選取器連結或附加,就如同字串一樣。這在 CSS 巢狀結構中無法運作,因為選取器不是字串,而是物件參照。

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

如需更深入的說明,請參閱規格

複雜巢狀結構範例

在選取器清單和 :is() 中建立巢狀結構

請考慮下列巢狀 CSS 區塊:

.one, #two {
  .three {
    /* some styles */
  }
}

這是第一個以挑選器清單開頭的範例,接著會繼續巢狀結構。先前的範例只會以選取器清單結束。這個巢狀結構示例並無無效項目,但在選取器清單中巢狀結構的實作細節可能會比較棘手,尤其是包含 ID 選取器的清單。

為了讓巢狀結構的用意生效,瀏覽器會將任何非最內層巢狀結構的選取器清單包裝在 :is() 中。這個包裝函式可在任何作者設定內容中維持選取器清單的群組。這個群組 (:is(.one, #two)) 的副作用是,它會採用括號內選取器中最高分數的特定性。:is() 一向運作的方式就是如此,但使用巢狀語法時可能會讓人感到意外,因為這並非編寫的內容。總結一下這個技巧:使用 ID 和選取器清單巢狀結構,可產生非常具體的選取器。

為了清楚重現這個複雜的範例,我們會將先前的巢狀區塊套用至文件,如下所示:

:is(.one, #two) .three {
  /* some styles */
}

請留意,或讓您的 Linter 在使用 ID 選取器的選取器清單中巢狀時發出警告,因為在該選取器清單中,所有巢狀的特定性都會很高。

混合巢狀結構和宣告

請考慮下列巢狀 CSS 區塊:

.card {
  color: green;
  & { color: blue; }
  color: red;
}

.card 元素的顏色會是 blue

任何混合樣式宣告都會提升至頂端,就好像是在發生任何巢狀結構之前編寫的一樣。詳情請參閱規格

但有其他方法可以解決這個問題。以下程式碼會將三種色彩樣式包裝在 & 中,以便維持作者可能想要的層疊順序。.card 元素的顏色會變成紅色。

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

事實上,建議您將巢狀結構後面的任何樣式包裝在 & 中。

.card {
  color: green;

  @media (prefers-color-scheme: dark) {
    color: lightgreen;
  }

  & {
    aspect-ratio: 4/3;
  }
}

特徵偵測

有兩種方法可用來偵測 CSS 巢狀結構:使用巢狀結構或使用 @supports 檢查巢狀選取器剖析功能。

Bramus 的 Codepen 示範螢幕截圖,詢問您的瀏覽器是否支援 CSS 巢狀結構。該問題下方有一個綠色方塊,表示有支援服務。

使用巢狀結構:

html {
  .has-nesting {
    display: block;
  }

  .no-nesting {
    display: none;
  }
}

使用 @supports

@supports (selector(&)) {
  /* nesting parsing available */
}

我的同事 Bramus 有一個很棒的 Codepen,說明這項策略。

使用 Chrome 開發人員工具進行偵錯

目前 DevTools 對巢狀結構的支援功能非常有限。目前您會發現樣式會如預期顯示在「樣式」窗格中,但系統尚不支援追蹤巢狀結構和完整的選取器內容。我們有相關設計和計畫,以便讓這項功能更公開透明。

Chrome 開發人員工具巢狀語法的螢幕截圖。

Chrome 113 預計將額外支援 CSS 巢狀結構。敬請期待!

未來

CSS Nesting 目前僅支援第 1 版。版本 2 將引入更多語法糖,且可能減少需要背誦的規則。許多人希望巢狀解析不會受到限制,或不會有棘手的情況。

巢狀結構是 CSS 語言的重大強化功能。這項功能對 CSS 幾乎所有架構層面都有影響。在有效指定第 2 版之前,必須深入探討並瞭解這項重大影響。

最後,這裡有一個示範,同時使用 @scope、巢狀結構和 @layer。這一切都令人興奮!

淺色資訊卡搭配灰色背景。資訊卡包含標題和文字、幾個動作按鈕和網路龐克風格的圖片。