@scope の「to (.scoped)」でコンポーネントのスタイル漏れを止める
各コンポーネントのルートに共通クラス(例: .scoped)を付け、@scope ... to (.scoped) でスコープの下限を切ると、子コンポーネントにスタイルが漏れなくなる。
どんな時に使う?
- CSS Modules やビルドツールに頼らず、Web標準だけでコンポーネント単位のスタイル隔離をしたいとき。
- ネストしたコンポーネントに親のセレクタ(
aやpなど)が効いてしまう事故を防ぎたいとき。 - 投稿者は「Web標準なので場所や環境を選ばない」点を CSS Modules との違いに挙げている。
コード
ルール: コンポーネントのルート要素には必ず .scoped を付ける。
html
<article class="card scoped">
<style>
/* プレリュードなしの @scope は親要素(.card)がスコープルートになる */
@scope to (.scoped) {
:scope { padding: 1rem; }
p { margin-block: 0.5em; } /* 子コンポーネント内の p には効かない */
}
</style>
<p>カード本文</p>
<div class="badge scoped">…子コンポーネント(ここが境界)…</div>
</article>外部 CSS ファイルに書く場合:
css
@scope (.card) to (.scoped) {
p { margin-block: 0.5em; }
}to (...)に一致する子孫要素(=ネストした子コンポーネントのルート)から内側はスコープ外になる(いわゆる「ドーナツスコープ」)。- 漏れなくなるのは「セレクタで当てたスタイル」で、
colorやfontなどの継承は通常どおり子に伝わる。
注意点・対応状況
@scopeは Chrome / Edge 118+、Safari 17.4+ で対応。Firefox は新しめのバージョンで対応したので、Can I use で要確認。- 名前の衝突(同じクラス名が別の場所で使われる)を防ぐ仕組みではない。クラス名のユニーク化は別途必要。
- チームで運用するなら「ルートに
.scopedを付ける」をリンターやレビューで強制するのが前提。