在學習基本 CSS 原理時,我們會學習如何編寫模組化、可重複使用和描述性的樣式,以確保可維護性。但是,當開發人員參與實際應用程式時,通常感覺不可能添加 UI 功能而不會將樣式洩漏到意外區域。 這個問題常常會像滾雪球一樣滾入自我實現的循環。理論上僅限於某個元素或類別的樣式開始出現在它們不屬於的地方。這迫使開發人員創建更特定的選擇器來覆蓋洩漏的樣式,然後意外地覆蓋全域樣式,等等。 嚴格的類別名稱約定(例如 BEM)是解決此問題的一種理論上的方法。 BEM(區塊、元素、修飾符)方法是一種命名 CSS 類別的系統方法,以確保 CSS 檔案內的可重複使用性和結構。像這樣的命名約定可以透過利用領域語言來描述元素及其狀態來減少認知負擔,並且如果正確實施,可以使大型應用程式的樣式更易於維護。 然而,在現實世界中,事情並不總是這樣。優先事項可能會發生變化,隨著變化,實施會變得不一致。對 HTML 結構的微小更改可能需要修改許多 CSS 類別名稱。對於高度互動的前端應用程序,遵循 BEM 模式的類別名稱可能會變得又長又笨拙(例如,app-user-overview__status--is-authenticating),並且不完全遵守命名規則會破壞系統的結構,從而抵消其好處。 考慮到這些挑戰,開發人員轉向框架也就不足為奇了,Tailwind 是最受歡迎的 CSS 框架。與其試圖打一場看似無法獲勝的樣式之間的特殊性戰爭,不如放棄 CSS Cascade 並使用保證完全隔離的工具更容易。 開發商更依賴公用事業 我們怎麼知道有些開發人員熱衷於避免級聯樣式?這是專門為此目的而設計的「現代」前端工具(例如 CSS-in-JS 框架)的興起。使用嚴格限制於特定組件的獨立樣式看起來像是呼吸新鮮空氣。它消除了命名事物的需要——這仍然是最令人討厭和最耗時的前端任務之一——並且允許開發人員在不完全理解或利用 CSS 繼承的好處的情況下提高工作效率。 但放棄 CSS Cascade 也有自己的問題。例如,在 JavaScript 中編寫樣式需要大量的建置配置,並且通常會導致樣式與元件標記或 HTML 尷尬地混合在一起。我們允許建置工具為我們自動產生選擇器和識別碼(例如 .jsx-3130221066),而不是仔細考慮命名約定,從而要求開發人員跟上另一種偽語言本身。 (好像理解所有組件的 useEffects 的作用的認知負荷還不夠!) 進一步將類別命名工作抽象化為工具意味著基本偵錯通常僅限於為開發而編譯的特定應用程式版本,而不是利用支援即時偵錯的本機瀏覽器功能,例如開發人員工具。 這幾乎就像我們需要開發工具來調試我們用來抽象網路已經提供的內容的工具一樣——所有這些都是為了擺脫編寫標準 CSS 的「痛苦」。 幸運的是,現代 CSS 功能不僅使標準 CSS 的編寫更加靈活,而且還為像我們這樣的開發人員提供了更多的能力來管理級聯並使其為我們工作。 CSS Cascade Layers 是一個很好的例子,但還有另一個功能卻令人驚訝地缺乏關注——儘管這種情況正在改變,因為它最近已經與 Baseline 相容。 CSS @scope At 規則 我認為 CSS @scope at-rule 是解決我們已經討論過的那種樣式洩漏引起的焦慮的潛在療法,它不會迫使我們為了抽象和額外的構建工具而犧牲原生 Web 優勢。 「@scope CSS at-rule 使您能夠選擇特定 DOM 子樹中的元素,精確定位元素,而無需編寫難以覆蓋的過於特定的選擇器,並且不會將選擇器與 DOM 結構耦合得太緊密。」— MDN
換句話說,我們可以在特定實例中使用獨立的樣式,而無需犧牲繼承、級聯,甚至基本的關注點分離這是前端開發長期存在的指導原則。 另外,它具有出色的瀏覽器覆蓋率。事實上,Firefox 146 在 12 月就添加了對 @scope 的支持,使其首次兼容 Baseline。以下是使用 BEM 模式與 @scope 規則的按鈕之間的簡單比較: <按鈕類別=“按鈕按鈕--primary”> 按鈕>
<風格> .button .button__text { /* 按鈕文字樣式 */ } .button .button__icon { /* 按鈕圖示樣式 */ } .button--primary { 主按鈕樣式 */ } 風格>
<按鈕類別=“主按鈕”> 點我 <跨度>→跨度> 按鈕>
<風格> @scope (.primary-button) { span:first-child { /* 按鈕文字樣式 */ } span:last-child { /* 按鈕圖示樣式 */ } } 風格>
@scope 規則允許以較低的複雜性實現精確性。開發人員不再需要使用類別名稱建立邊界,這反過來又允許他們基於本機 HTML 元素編寫選擇器,從而消除了對規定 CSS 類別名稱模式的需求。透過簡單地消除類別名稱管理的需要,@scope 可以減輕大型專案中與 CSS 相關的恐懼。
基本用法
首先,將 @scope 規則加入 CSS 中,並插入一個根選擇器,樣式將被限定在該根選擇器中:
@scope (<選擇器>) {
/* 樣式範圍僅限於
因此,例如,如果我們將樣式範圍限定為
@範圍(導航){ a { /* 導航範圍內的連結樣式 */ }
a:active { /* 活動連結樣式 */ }
a:active::before { /* 帶有偽元素的活動鏈接,用於額外的樣式 */ }
@media(最大寬度:768px){ a { /* 響應式調整 */ } } }
就其本身而言,這並不是一個突破性的功能。但是,可以將第二個參數新增至範圍以建立下邊界,從而有效地定義範圍的起點和終點。
/* ul 內的任何 a 元素都不會套用樣式 */ @scope (nav) 到 (ul) { 一個{ 字體大小:14px; } }
這種做法稱為甜甜圈作用域,可以使用多種方法,包括一系列與 DOM 結構緊密耦合的類似、高度特定的選擇器、:not 偽選擇器,或為
/*
結論 實用性優先的 CSS 框架(例如 Tailwind)非常適合原型設計和小型專案。然而,當在涉及多個開發人員的大型專案中使用時,它們的好處很快就會減弱。 近幾年來,前端開發變得越來越複雜,CSS 也不例外。雖然 @scope 規則並不是包治百病,但它可以減少對複雜工具的需求。當取代策略類別命名或與策略類別命名一起使用時,@scope 可以使編寫可維護的 CSS 變得更容易、更有趣。 進一步閱讀
CSS @scope (MDN) “CSS @scope”,胡安·迭戈·羅德里格斯 (CSS-Tricks) Firefox 146 發行說明 (Firefox) 瀏覽器支援(CanIUse) 流行的 CSS 框架(CSS 2024 現況) “CSS 中的“C”:Cascade”,Thomas Yip(CSS-Tricks) BEM簡介(取得BEM)