CSSでコンポーネントを作っていると、最後にしんどくなるのは「どのセレクタが勝っているのか分からない」問題です。最初は.card h2くらいで済んでいたのに、ページが増えると.page .section .card h2みたいな指定が増えていきます。
そこで今見ておきたいのが@scopeです。ざっくり言うと、CSSの効く範囲を特定のDOMツリーに閉じるためのルールです。CSS ModulesやShadow DOMほど大きな仕組みにしなくても、普通のCSSのまま「この部品の中だけ」を指定しやすくなります。
CSS @scopeとは
@scopeは、指定したルート要素の中だけにスタイルを適用するCSSのat-ruleです。MDNではBaseline 2025の機能として扱われていて、今後の素のCSS設計ではかなり重要になると思っています。
@scope (.article-card) {
h2 {
font-size: 1.4rem;
}
p {
line-height: 1.8;
}
}
この場合、.article-cardの中にあるh2やpだけが対象になります。ページ全体のh2へ広がらないので、後から読み返した時に意図が追いやすいです。
まずはこの形で使う
実務で最初に使うなら、カード、CTA、プロフィール、記事内の補足ボックスのような「小さく完結したUI」からが安全です。
HTML
<section class="profile-card">
<h2>Enough Basketball Idiot</h2>
<p>記事、ツール、バスケの記録をまとめていく場所です。</p>
<a href="#">記事を見る</a>
</section>
<section class="note-card">
<h2>別のカード</h2>
<p>こちらは同じh2でも別ルールで見せたい。</p>
</section>
CSS
@scope (.profile-card) {
:scope {
max-width: 520px;
padding: 24px;
border: 1px solid #d9e2f2;
border-radius: 8px;
background: #ffffff;
color: #111827;
}
h2 {
margin: 0 0 12px;
font-size: 28px;
line-height: 1.25;
}
p {
line-height: 1.8;
color: #4b5563;
}
a {
display: inline-flex;
margin-top: 12px;
color: #0b4dff;
font-weight: 700;
}
}
@supports not selector(:scope) {
.profile-card h2 {
font-size: 28px;
}
}
:scopeの使いどころ
@scopeの中で:scopeを書くと、スコープのルート要素そのものを指定できます。上の例だと.profile-card自体の余白や背景を:scopeで書いています。
@scope (.profile-card) {
:scope {
padding: 24px;
border: 1px solid #d9e2f2;
}
h2 {
margin-block-start: 0;
}
}
@scopeが向いている場面
- WordPressテーマ内の共通パーツを整理したい
- 記事本文用のスタイルとカード用のスタイルを混ぜたくない
- LPの一部だけ違う見た目にしたい
- CSS Modulesまでは入れたくないが、セレクタの影響範囲は狭めたい
- 詳細度を上げ続ける運用から抜けたい
@layerとの違い
| 機能 | 役割 | 向いていること |
|---|---|---|
| @layer | カスケードの優先順位を層で管理する | reset、base、components、utilitiesの整理 |
| @scope | スタイルの適用範囲をDOMツリーで絞る | 部品単位のスタイル漏れ防止 |
| CSS Modules | ビルド時にクラス名を分離する | ReactやAstroなどのコンポーネント開発 |
| Shadow DOM | DOMとCSSを強くカプセル化する | Web Components |
自分なら、サイト全体の大枠は@layer、部品単位の漏れ防止に@scope、アプリ寄りのUIではCSS Modules、という感覚で使い分けます。全部を置き換えるというより、今あるCSS設計に足す道具です。
注意点
- 古いブラウザまで強く見る案件では、通常のクラス指定をfallbackとして残す
- スコープを深くしすぎると、結局読みづらいCSSになる
- ページ全体のレイアウト指定には向かない
- ブラウザ実装差が残る部分は、実機で確認する
あわせて読みたい
参考資料
まとめ
@scopeは、CSSを「ページ全体へ広げるもの」から「部品の中に閉じるもの」へ寄せてくれます。WordPressテーマでも、Astroでも、静的なHTMLでも使い道があります。
いきなり全CSSを置き換える必要はありません。まずはカードやCTAのような小さなUIに使って、セレクタの見通しが良くなるか試すのがちょうどいいです。