層級串連 (@layer
CSS 規則) 即將在 Chromium 99、Firefox 97 和 Safari 15.4 Beta 中推出。可讓您更明確地控制 CSS 檔案,避免樣式專屬性衝突。這對於大型程式碼集、設計系統,以及在應用程式中管理第三方樣式時特別實用。
以清楚的方式分層 CSS 可避免意外的樣式覆寫,並促進更優質的 CSS 架構。
CSS 特殊性和層疊
CSS 特異性是 CSS 決定要將哪些樣式套用至哪些元素的方式。您可以使用不同的選取器,決定任何樣式規則的特定性。舉例來說,元素的特定性低於類別或屬性,而類別或屬性的特定性又低於 ID。這是學習 CSS 的基礎知識。
為了避免不小心覆寫特定性,許多人會採用 BEM 等 CSS 命名慣例。為所有內容提供單一類別名稱,即可將所有內容置於相同的特定性平面。不過,您不一定能維持這種有條理的樣式,尤其是在使用第三方程式碼和設計系統時。
而分層式層級就是為瞭解決這個問題。這些屬性會在 CSS 階層中引入新的層。在使用分層樣式時,層的優先順序一律高於選取器的特定性。
舉例來說,選取器 .post a.link
的特定性高於 .card a
。如果嘗試在文章中的資訊卡中設定連結樣式,系統會套用更精確的選取器。
使用 @layer
時,您可以更明確地指定各樣式的特定性,並確保資訊卡連結的樣式會覆寫貼文連結的樣式,即使所有 CSS 都位於同一平面,特定性在數值上可能會較低。這是因為階層優先順序。分層樣式會建立新的層疊「平面」。
@layer
應用實例
這個範例使用 @layer
展示串連層的強大功能。畫面上會顯示多個連結:有些連結沒有套用任何額外的類別名稱、有些連結套用 .link
類別,有些連結套用 .pink
類別。接著,CSS 會新增三個圖層:base
、typography
和 utilities
,如下所示:
@layer base {
a {
font-weight: 800;
color: red; /* ignored */
}
.link {
color: blue; /* ignored */
}
}
@layer typography {
a {
color: green; /* styles *all* links */
}
}
@layer utilities {
.pink {
color: hotpink; /* styles *all* .pink's */
}
}
最後,所有連結都會顯示為綠色或粉紅色。這是因為:雖然 .link
的選取器層級特定性高於 a
,但 a
的顏色樣式在優先順序較高的 @layer
中。當綠色規則位於藍色規則後面的圖層時,a { color: green }
會覆寫 .link { color: blue }
。
層級優先順序優於元素明確性。
整理圖層
您可以直接在頁面上整理圖層,如上圖所示,也可以在檔案頂端整理圖層。
圖層順序是由每個圖層名稱在程式碼中首次出現時建立。
也就是說,如果您在檔案頂端新增下列內容,連結就會全部顯示紅色,而類別為 .link
的連結則會顯示藍色:
@layer utilities, typography, base;
這是因為現在的圖層順序已反轉,先顯示公用程式,再顯示基礎圖層。因此,base
圖層中的樣式規則一律會比字體排版圖層中的樣式規則更具特異性。這些連結不再是綠色,而是紅色或藍色。
整理匯入項目
另一種使用 @layer
的方式是匯入檔案。您可以在匯入樣式時直接執行此操作,方法是使用 layer()
函式,如以下範例所示:
/* Base */
@import '../styles/base/normalize.css' layer(base); /* normalize or rest file */
@import '../styles/base/base.css' layer(base); /* body and base styles */
@import '../styles/base/theme.css' layer(theme); /* theme variables */
@import '../styles/base/typography.css' layer(theme); /* theme typography */
@import '../styles/base/utilities.css' layer(utilities); /* base utilities */
/* Layouts */
@import '../styles/components/post.css' layer(layouts); /* post layout */
/* Components */
@import '../styles/components/cards.css' layer(components); /* imports card */
@import '../styles/components/footer.css' layer(components); /* footer component */
上述程式碼片段有三個層級:base
、layouts
和 components
。base
中的 normalize、主題和字體排版檔案,layouts
中的 post
檔案,以及 components
中的 cards
和 footer
。匯入檔案時,系統會使用圖層函式將圖層例項化。另一種做法是在檔案頂端整理圖層,並在任何匯入作業之前宣告圖層:
@layer base,
theme,
layouts,
components,
utilities;
如今,您 @import
樣式的順序對圖層順序沒有影響,因為圖層順序已在圖層名稱的首個例項中建立。這樣就少了一項讓人擔心的事。您還是可以將匯入的檔案設為特定圖層,但順序已確定。
層級和階層
讓我們回顧一下,看看層級在哪些地方與更廣泛的層級相關:
優先順序如下:
- 使用者代理程式正常 (最低優先順序)
- 本機使用者 @layer
- 本機使用者正常
- 作者 @layers
- 作者正常
- 作者 !important
- 作者 @layer !important
- 本機使用者 !important
- 使用者代理程式 !important** (最高優先順序)
您可能會發現 @layer !important
樣式已反轉。相較於非分層 (一般) 樣式,它們具有較高的優先順序,這是因為 !important
在層疊中的作用方式:它會中斷樣式表中的正常層疊,並反轉正常的層級層級特異性 (優先順序)。
巢狀圖層
您也可以在其他圖層中嵌套圖層。以下範例取自 Miriam Suzanne 的層級式疊代說明:
@layer default {
p { max-width: 70ch; }
}
@layer framework {
@layer default {
p { margin-block: 0.75em; }
}
p { margin-bottom: 1em; }
}
在上述程式碼片段中,您可以使用 .
存取 framework.default
,並將 .
做為 default
層在 framework
中巢狀結構的標記。您也可以使用更簡略的格式編寫:
@layer framework.default {
p { margin-block: 0.75em }
}
產生的圖層和圖層順序如下:
- 預設
framework.default
framework
未分層- 未分層
注意事項
只要正確使用,階層式層級就能發揮極大效用,但也可能造成混淆,並產生非預期的結果。使用級聯層時,請注意下列事項:
規則 1:請勿使用 @layer
進行範圍設定
分層設定無法解決範圍設定問題。如果您有含 @layer
的 CSS 檔案 (例如 card.css
),且想要為資訊卡中的所有連結套用樣式,請勿編寫以下樣式:
a {
…
}
這麼做會導致檔案中的所有 a
標記都收到這個覆寫值。不過,您還是需要正確設定範圍樣式:
.card a {
…
}
規則 2:分層圖層的排序會排在非分層 CSS 後方
請注意,分層 CSS 檔案「不會」覆寫非分層 CSS。我們刻意做出這個決定,讓您能以更合理的方式引入圖層,以便與現有的程式碼庫搭配使用。例如,使用 reset.css
檔案是建立層疊式圖層的良好起點和用途。
規則 3:!important
會反轉層疊的特定性
雖然一般來說,分層樣式不如非分層樣式具體,但使用 !important
可反轉這個情況。在圖層中,使用 !important
規則的宣告比未分層樣式更具特徵。
在這種情況下,!important
樣式會反轉其特定性。請參考下方圖表:author @layer 的優先順序低於 author normal,而 author normal 的優先順序低於 author !important,而 author !important 的優先順序低於 author @layer !important。
如果您有多個圖層,第一個含有 !important
的圖層會優先採用 !important
,並成為最具體的樣式。
規則 4:瞭解注入點
由於每個圖層名稱在程式碼中首次出現時就會建立圖層順序,因此如果您在匯入及設定 layer()
之後,或在其他 @layer
陳述式之後放置 @layer
宣告,系統會忽略該宣告。與 CSS 不同的是,CSS 會將網頁最底部的樣式規則套用至層疊層,而此處則會在初始例項中建立順序。
這可以是清單、圖層區塊或匯入內容。如果在含有 layer()
的匯入清單後方加入 @layer
,系統不會執行任何動作。將其放在檔案頂端,即可設定圖層順序,並清楚查看架構中的圖層。
規則 #5:留意精確度
在階層層級中,如果較不精確的選取器 (例如 a
) 位於較精確的層級,就會覆寫較精確的選取器 (例如 .link
)。請把握以下幾項重點:
如果指定了 @layer utilities, components
,layer(components)
中的 a
會覆寫 layer(utilities)
中的 .pink
。雖然這是 API 的預設行為,但如果您不預期會發生這種情況,可能會感到困惑和沮喪。
因此,如果您要編寫公用類別,請一律將其納入比要覆寫的元件更高階的層級。您可能會想:「我剛剛新增了這個 .pink
類別來變更顏色,但並未套用」。
進一步瞭解串連層
如要進一步瞭解串連層,請參考下列資源: