原生 CSS 巢狀(Nesting)終於來了!

4 分鐘

1. 那個我們用了十年的「非官方」功能

如果你寫過幾年前的前端程式碼,一定對 Sass 或 Less 不陌生。在這些 CSS 前處理器中,有一個功能幾乎是所有開發者的最愛:選擇器巢狀(Nesting)。它允許我們像寫 HTML 一樣,將子選擇器的規則寫在父選擇器內部,大幅提升程式碼的可讀性和組織性。

// Sass 语法
nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}

多年來,我們一直依賴建置工具將這種語法編譯成瀏覽器認得的普通 CSS。但現在,情況變了。

2. 原生 CSS 巢狀登場

從 2023 年初開始,主流瀏覽器(Chrome、Safari、Firefox)陸續宣布支援原生 CSS Nesting Module。這表示,我們可以直接在 .css 檔案裡編寫巢狀規則,無須任何前處理。

上面的範例用原生 CSS 可以這樣寫:

/* 原生 CSS 语法 */
nav {
  ul {
    margin: 0;
    padding: 0;
    list-style: none;
  }

  li { display: inline-block; }

  a {
    display: block;
    padding: 6px 12px;
    text-decoration: none;
  }
}

是的,它看起來和 Sass 完全一樣!

3. & 的重要角色

和前處理器一樣,& 符號在原生巢狀中也扮演關鍵角色,它代表父選擇器。這在處理虛擬類別、虛擬元素或組合選擇器時非常有用。

.card {
  background: white;
  border-radius: 8px;

  /* & 代表 .card */
  &:hover {
    box-shadow: 0 4px 12px rgba(0,0,0,0.1);
  }

  /* & 代表 .card,组合成 .card.dark-mode */
  &.dark-mode {
    background: #333;
  }

  /* & 代表 .card,组合成 .card > .header */
  > .header {
    font-weight: bold;
  }
}

4. 與 Sass 的一個微小但重要的差異

在 Sass 中,你可以直接巢狀類別選擇器,例如 .card { .title { ... } }。在原生 CSS Nesting 的早期規範中,這是不允許的,任何巢狀規則都必須以一個符號(如 &>+~)開頭。

雖然最新規範放寬了這一限制,允許直接巢狀標籤選擇器(如 article { h1 { ... } }),但在巢狀類別選擇器時,為了明確並避免歧義,最佳實務仍然是使用 &

/* 推荐写法 */
.article {
  & .author-name {
    font-style: italic;
  }
}

/* 不推荐的写法 (在某些早期实现或严格解析器中可能无效) */
.article {
  .author-name {
    font-style: italic;
  }
}

使用 & 可以清楚表達 .author-name.article 的後代。

5. 瀏覽器支援與未來

截至 2023 年 9 月,所有主流現代瀏覽器(Chrome 112+、Safari 16.5+、Firefox 117+)均已支援 CSS Nesting。這表示我們可以開始在正式環境中逐步使用它。

原生 CSS 巢狀的到來,是 Web 平台自身演進的另一個重要里程碑。它減少我們對建置工具的依賴,讓 CSS 本身變得更強大且富有表現力,也讓剛入門的前端開發者能更直觀地編寫和理解樣式程式碼。