現代 CSS 解決方案:原生巢狀(Nesting)

2023-09-11 12:02:37

很早之前,就寫過一篇與原生巢狀相關的文章 -- CSS 即將支援巢狀,SASS/LESS 等前處理器已無用武之地?,彼時 CSS 原生巢狀還處於工作草案 Working Draft (WD) 階段,而今天(2023-09-02),CSS 原生巢狀 Nesting 終於成為了既定的規範!

CSS 原生巢狀語法

在之前,只有在 LESS、SASS 等前處理器中,我們才能使用巢狀的寫法,像是這樣:

div {
    & > p {
        color: red;
    }

    &:hover {
        color: yellow;
    }
}

從 Chrome 112 開始,原生 CSS 也可以使用巢狀語法了。

其語法規則大致如下:

parentRule {
  /* parent rule style properties */
  & childRule {
    /* child rule style properties */
  }
}

CSS 原生巢狀語法能力邊界

大部分同學對巢狀應該還是非常熟悉的,下面我們一起看看,CSS 原生巢狀的能力邊界,語法支援範圍。

支援巢狀,並且支援多層巢狀

這個很好理解,直接看 DEMO:

<div class="g-container">
    <h3 class="g-h3">CSS 
        <span class="g-span">Nesting</span>
    </h3>
</div>
div {
    border: 1px solid #000;
    
    .g-h3 {
        color: red;
        
        .g-span {
            color: blue;
        }
    }
}

效果如下:

當然,這裡有個值得注意的點。如果我們不使用具體的 ClassName,而是使用標籤名稱選擇器,像是這樣:

div {
    border: 1px solid #000;
    
    h3 {
        color: red;
        
        span {
            color: blue;
        }
    }
}

巢狀規則是不會生效的,此時,我們需要在標籤名稱選擇器前,加上 & 符合:

div {
    border: 1px solid #000;
    
    & h3 {
        color: red;
        
        & span {
            color: blue;
        }
    }
}

與 SASS 等類似,& 符號在巢狀中,也表示巢狀的父選擇器本身,因此,上面兩個巢狀選擇器最終的表示式實則為:

  • div h3 { color: red };
  • div h3 span { color blue };

在巢狀中使用偽元素和偽類

直接上程式碼,這個也是傳統 CSS 前處理器支援的內容:

div {
  /* ... */
  &:hover {
    color: red;
  }

  &:is(.content, footer) {
    padding: 16px;
  }

  &::before {
    content: "";
    /* ... */
  }
}

上述程式碼中,我們能夠在巢狀中使用偽類、偽元素。

在巢狀中使用媒體查詢

這個就比較有意思了,我們甚至可以在巢狀中,使用媒體查詢語法。

<div class="g-container">
    <h3>CSS Nesting without @media</h3>
</div>
<div class="g-container media">
    <h3>CSS Nesting with @media</h3>
</div>

.media {
  @media (min-width: 600px) {
      & h3 {
          color: red;
      }
  }
}

此時,下方帶有 .media class 的容器,在視口寬度大於 600px 的時候,設定 color: red

效果如下:

完整的 DEMO,你可以戳這裡試一下:CodePen Demo -- CSS Nesting Demo

在巢狀中巢狀自身

哈?什麼是在巢狀中巢狀自身

其實也很好理解,也就是 & 符號的時候,上面提到了,& 符號在巢狀中,也表示巢狀的父選擇器本身,因此,我們還可以有這樣的寫法:

div {
    & h2 & {
        /* 表示 div h2 div {} */
    }
}

這種寫法也是允許的,我們只需要將 & 替換成 div 即可,此時表示 div h2 div {}

總結一下

總結而言,CSS 原生的巢狀功能相當強大,基本是傳統前處理器的平替。使用巢狀規則的好處在於:

  1. 更加易讀和易維護,巢狀幫助我們編寫更易於維護的 CSS,基於巢狀,我們可以更好的控制樣式的作用域
  2. 更少的程式碼,巢狀幫助我們編寫更少的程式碼,因為我們不需要一遍又一遍地重複父選擇器

隨著相容性的鋪開,慢慢地,我們可以嘗試真正運用它們到實際程式碼中。

最後

好了,本文到此結束,希望對你有幫助