CSS 範疇控制 (CSS Scope)
@scope 是 CSS 的一項新特性,它允許開發者將樣式明確地限制在文件中的特定區域內。這解決了長期以來 CSS 樣式容易「溢出 (Leak)」到其他組件的問題,而不再需要完全依賴 BEM 或 CSS Modules 等外部工具。
什麼是 @scope?
傳統 CSS 是全域的,除非你使用非常具體的選擇器。@scope 則讓你宣告:「這些樣式只對在這個元素內部的東西生效」。
@scope (.card) {
/* 這裡的 img 只會影響 .card 內部的圖片 */
img {
border-radius: 8px;
}
.title {
font-size: 1.25rem;
}
}
對應的 HTML:
<div class="card">
<img src="photo.jpg" />
<h2 class="title">卡片標題</h2>
<p>這張圖片會有圓角,且標題顏色會變動。</p>
</div>
<!-- 外部的圖片不會受到影響 -->
<img src="other.jpg" />
甜甜圈範疇 (Donut Scoping)
@scope 最強大的地方在於「範圍限制(Scoping Limit)」,這被暱稱為「甜甜圈範疇」。你可以定義一個範圍的起點,並排除特定子區域的樣式。
/* 起點是 .card,但當遇到 .content 時停止作用 */
@scope (.card) to (.content) {
img {
border: 5px solid red;
}
}
對應的 HTML:
<div class="card">
<img src="outer.jpg" />
<!-- 會套用紅框 -->
<div class="content">
<img src="inner.jpg" />
<!-- 不會套用紅框,因為進入了排除範圍 -->
</div>
</div>
這在處理「卡片中嵌入了另一個獨立組件」的場景非常有用,避免父組件的樣式意外影響到子組件。
特殊符號 :scope
在使用 @scope 時,:scope 偽類代表的是目前範圍的「根元素」。
@scope (.article) {
/* 這裡的 :scope 指的就是 .article 元素本身 */
:scope {
padding: 2rem;
background: #f9f9f9;
}
p {
color: #333;
}
}
對應的 HTML:
<div class="article">
<p>這個 div 本身會有背景色與內距,內部的文字則是深灰色。</p>
</div>
為什麼要使用 @scope?
- 更乾淨的選擇器:不需要撰寫長長的
.navbar .nav-list .nav-item a,直接在@scope (.navbar)內撰寫a即可。 - 權重管理:在
@scope內定義的樣式,其優先權計算方式能更好地與 DOM 結構吻合,減少樣式衝突。 - 原生封裝:接近 Shadow DOM 的行為,但更輕量且不需要 JavaScript。
實務範例
@scope (.sidebar) {
/* 僅作用於側邊欄內的連結 */
a {
display: block;
color: gray;
&:hover {
color: black;
}
}
}
對應的 HTML:
<aside class="sidebar">
<nav>
<a href="#">首頁</a>
<a href="#">關於我們</a>
</nav>
</aside>
瀏覽器支援度
@scope 目前已在 Chrome 118+ 與 Safari 17.4+ 中正式支援。雖然 Firefox 目前(2025 年初)仍在開發階段,但這項功能已被視為現代組件化開發的核心組成部分。
如果你正在開發中大型專案或使用 React/Vue 等組件化框架,
@scope 是除了 CSS Modules 之外另一個非常值得考慮的原生樣式封裝工具。