巢狀結構

巢狀 CSS 樣式規則可讓樣式表更有條理、更容易閱讀及維護。

總覽

瞭解選取器後,您可能會想知道如何在樣式表內更妥善地整理選取器。假設您要為網站「功能」部分中的項目套用樣式,使用巢狀結構時,您可以將這些樣式分組到 .feature 規則中,如下所示:

.feature {
  button {
    color: blue;
  }

  .link {
    color: red;
  }

  .text {
    font-size: 1.3em;
  }
}

這與分別編寫每個樣式相同:

.feature button {
  color: blue;
}

.feature .link {
   color: red;
}

.feature .text {
   font-size: 1.3em;
}

巢狀結構可視需要深入多個層級。

.feature {
  .heading {
    color: blue;

    a {
      color: green;
    }
  }
}

分組及建立關係

巢狀結構可讓您更簡潔地分組,並建立樣式規則之間的關係。

根據預設,巢狀規則會以後代組合子的形式與外部規則相關。使用巢狀規則的選取器變更關係。

/* targets headings that are siblings of the .feature element and come immediately after it */
.feature {
  + .heading {
    color: blue;
  }

/* targets all paragraphs that are direct children of the .feature element */
  > p {
    font-size: 1.3em;
  }
}

使用 & 選取器定義明確關係

您也可以使用 & 選取器,在巢狀樣式規則中更明確地指定樣式。請將 & 視為代表父項選取器的符號。

.feature {
 & button {
    color: blue;
  }
}

這相當於以下列方式編寫樣式:

.feature button {
  color: blue;
}

何時需要 &

如果沒有 &,巢狀選取器會是父項選取器的後代選取器。如要形成複合選取器& 必須

.feature {
  &:last-child {
    /* Selects the .feature element that is the :last-child, equivalent to .feature:last-child */
  }
   
  & :last-child {
    /* Selects the :last-child inside of a .feature element, equivalent to .feature :last-child */
  }

  &.highlight {
    /* Selects .feature elements that also have a .highlight class, equivalent to .feature.highlight */
  }

  & .highlight {
     /* Selects elements inside of the .feature element with the class .highlight, equivalent to .feature .highlight */
  }
}

您也可以變更內容,並將 & 選取器放在子項選取器的結尾,或放在子項選取器的兩側。


/* Targets buttons with an adjacent sibling button */
button {
  & + & {
    /* … */
  }
}
img {
  .my-component & {
    /* styles for images inside of `.my-component` ... */
  }
}

在最後一個範例中,我們為 .my-component 類別的元素內圖片新增樣式。如果您正在處理的專案無法在元素中新增 classid,這項功能就非常實用。

巢狀結構和精細設定

:is() 類似,巢狀選取器會採用父項選取器清單中特異性最高的選取器特異性。

#main-header,
.intro {
  & a {
    color: green;
  }
}

.intro a {
  color: blue;
}

第一條規則會指定 #main-header.intro 元素內的所有連結,並將這些連結設為綠色。

第二條規則會嘗試覆寫這項設定,將 .intro 元素內的連結設為藍色。

如果查看每條規則的明確性,就能瞭解為何這項做法無效。

/* equivalent to :is(#main-header, .intro) a with a specificity of (1, 0, 1) */
#main-header,
.intro {
  & a {
    color: green;
  }
}

/* lower specificity of (0, 1, 1) */
.intro a {
  color: blue;
}

由於第一個規則的選取器清單中含有 id,且巢狀規則會採用選取器中最高特異性的選取器,因此第一個規則的特異性高於第二個規則。即使 a 元素不在含有 #main-header 選擇器的元素內,連結也會顯示為綠色。

巢狀結構無效

:is() 類似,巢狀選取器無法代表虛擬元素。

blockquote, blockquote::before, blockquote::after {
  color: navy;

  & {
    border: 1px solid navy;
  }
}

您會預期 blockquote 和其虛擬元素都有 navy 色彩的文字和邊框,但事實並非如此。由於 & 選擇器無法代表虛擬元素,因此巢狀邊框樣式只會套用至 blockquote。

使用 & 和型別選取器建立複合選取器時,型別選取器必須放在最前面,且兩者之間不得有任何空白。

/* valid css nesting */
.feature {
  p& {
    font-weight: bold;
  }
}

/* invalid css nesting */
.feature {
  &p {
    font-weight: bold;
  }
}

這項規則可讓 CSS 巢狀結構與 Sass 等前置處理工具搭配運作。在 Sass 中,寫入 &p 會將父項選取器附加至巢狀類型選取器,結果會是 .featurep

巢狀 at 規則

CSS 條件式群組規則 (例如 @container@media@supports@layer) 也可以巢狀化。

.feature {
  @media (min-width: 40em) {
    /* ... */
  }

  @container (inline-size > 900px) {
    /* ... */
  }
}

.feature {
  @supports (display: grid) {
    /* ... */
  }
}

.feature {
  @layer component {
    h2 {
      /* ... */
    }
  }
}

隨堂測驗

使用 CSS Nesting 時,& 選取器代表什麼?

巢狀子項選取器
答錯了。
父項選取器
答對了!
最接近的同層元素選取器
答錯了。

巢狀結構最多只能有兩層。

答錯了。
答對了!

哪些 at 規則可以巢狀化?

@media
答對了!
@container
答對了!
@import
答錯了。
@supports
答對了!
@layer
答對了!