CSS Cascade Layers 權重 Specificity
CSS 前端工程

CSS Cascade Layers (@layer),解決長期以來 CSS 競爭權重 (Specificity) 的問題

FB公開社團 Larry的午茶時光
加入不需審核,歡迎讀者加入~
我的IG帳號: larry.time.taste。剛剛起步,歡迎大家追蹤~

前幾天看到一篇文章
https://developer.chrome.com/blog/cascade-layers/

Chromium 99、Firefox 97、Safari 15.4 將會支援 CSS Cascade Layers。雖然全瀏覽器的支援度還是不夠,但這幾家瀏覽器的大廠支援,就說明了 Cascade Layers 會成為未來的規格。

Cascade Layers 的官方文件在這裡
https://www.w3.org/TR/css-cascade-5/#layering

上面文件是 CSS Cascading and Inheritance Level 5,此份文件從 Level 3 到撰文的此時 (2022年2月) 已經出到 Level 6。CSS Cascading and Inheritance 就是負責定義在多個 CSS 語法下,一個 HTML element,最終是採用哪一個 CSS。

CSS Cascade 中很重要的一件事,就是搞清楚 Specificity (權重) 的概念。一般來講,用 HTML ID 來指定 CSS 的權重會大於用 CSS class,用 CSS class 來指定 CSS 的權重又大於用 HTML tag。

前幾年有人提出 BEM (Block Element Modifier) 命名的概念,它就是依照 HTML 區塊、區塊裡的元素、modifier 等,把所有名稱連起來,寫一個長長的 CSS selector。經驗夠的工程師就知道,這樣多難維護啊。重點是專案要快速完成吧,而不是把團隊的精力時間花在維護 BEM 命名。

稍微有點規模的專案,都有著複雜的 HTML 結構。你在開發某一頁時,根本不會知道你寫的這一個 CSS,跟已存在的 CSS 到底誰的權重重。如果已存在的 CSS 權重重,就暴力覆寫,大概會是這樣的情況。一整個專案的 CSS 有點像是在同一個平面,沒有任何結構,彼此競爭。

新的規格 Cascade Layers 試圖解決這個問題。以優先級來講,永遠先考慮 Cascade Layers,再考慮 Specificity (權重)。

我們來看一段 sample code

@layer base {
  div.abc {
    color: red;
  }
}

@layer theme {
  div {
    color: green;
  }
}

如果現在 HTML 裡有一個 <div class="abc">,裡面的字是什麼顏色?以權重來講,有指定 .abc 當然權重比較高。但是因為有使用 @layer,後宣告的 @layer 永遠覆寫之前宣告的 @layer,所以 <div class="abc"> 裡面的字是綠色。

在 CSS 檔案最上方,可以明確指定 layer 順序,例如加這一行到 CSS 檔案最上方

@layer theme, base; // 明確指定先 theme 再 base

這樣 @layer base 裡指定的 CSS 就會覆寫 @layer theme 裡指定的 CSS。

如同名稱 Cascade Layers,它把本來在同一個平面,互相競爭(權重)的 CSS,上下分層了。當然一般狀況,先宣告 base layer (下層),再宣告 theme layer (上層),甚至客製的元件 layer (更上層)。

上方 Chrome Developer 的文章有提醒

  1. 在 @layer 中的 CSS selector 仍然要寫全稱。本來寫什麼,在 @layer 裡就寫什麼,不要誤解 @layer 可以讓你的 CSS 少寫什麼。
  2. 如果同時有 layered / non-layered CSS,non-layered CSS 永遠先被採用,不管它的 selector 權重如何。所以要導入 Cascade Layers,先從基底的 CSS 開始導入,才不會影響整個專案。
  3. !important 會反轉優先順序。承第二點,如果同時有 layered / non-layered CSS,而且同時有 !important,@layer !important 的優先級高。
    如果同時有多個 layered CSS,而且同時有 !important,第一個 layered CSS with !important 的優先級最高。
    不管是 layered / non-layered 比較,多個 layer 比較,!important 都反轉了優先順序。
  4. @layer 的語法是宣告新的 layer。例如一 layer abc,如果你
    @import '....' layer(abc);
    之後再宣告 @layer abc,這個 @layer abc 無效。不會有任何權重,是完全被忽略。
    總之,Chrome Developer 的文章建議,CSS 檔案一開始就宣告 @layer,另一方面也明確的指定 layer order。

結論

Chromium 99、Firefox 97、Safari 15.4 將會支援 CSS Cascade Layers,這幾家瀏覽器的大廠支援,說明了 Cascade Layers 會成為未來的規格。

本篇文章走了一遍 CSS Specificity (權重),但長期以來全部 CSS 在同一平面競爭權重,有總是暴力覆寫的問題。Cascade Layers 可以將整個專案的 CSS 結構化,由下到上分為 base, theme, components 等,是一個合理又聰明的做法。上方圖層 (layer) 覆蓋下方圖層,也是一個清楚而直覺的想像。

Cascade Layers 可能會成為未來的規格,值得投資時間,有在做前端的讀者可以參考看看囉。

延伸閱讀:從 Compat 2021 到 Interop 2022,史上第一次所有主流的瀏覽器廠商,合作解決瀏覽器相容性的問題

FB公開社團 Larry的午茶時光
加入不需審核,歡迎讀者加入~
我的IG帳號: larry.time.taste。剛剛起步,歡迎大家追蹤~