mosya

CSSの適用範囲を限定する@scopeについて

@scopeとは

CSSの@scopeは、CSSの適用範囲を指定するためのルールです。

例えば、下のコードのように@scopeを使ってスタイルを指定すると、main要素内のdiv要素にだけスタイルが適用されます。

@scope (main) {
  div {
    background-color: red;
  }
}

ちょうど下の画像のように、@scopeの中で指定した要素の範囲内だけにスタイルが適用されるイメージですね!

実際にコードの実行結果をChromeブラウザーで確認してみましょう👇

main要素内の要素にだけスタイルが適用されていることがわかりますね!

さらに@scopeルールの中で:scopeセレクターを指定することで、@scopeルールの中の一番親である要素に対してCSSを指定することができます。

例えば以下の例では@scopeの親はmain要素なので、:scopeを使うことでmain要素に対してスタイルを指定することができますね!

ブラウザーのサポート状況

ちなみに今回の記事で取り上げる@scopeですが、
2023年11月現在まだChromeやEdgeなどのブラウザーでしかサポートされていません。

今のところ、各ブラウザーでサポートされるまでは使用を控えた方が良いでしょう。
それを踏まえて残りの記事を読んでいただけると幸いです。

@scopeの魅力

@scopeの魅力としてCSSの適用範囲をtoを使ってさらに細かく指定できることが挙げられます。

例えば以下のようなHTMLがあったとします。

<main>
  <section class="section1">
    <h2>section1</h2>
    <section class="section2">
      <h2>section2</h2>
    </section>
  </section>
</main>

この時、section1内のh2だけにスタイルを適用したい場合、@scopeを使って以下のように指定できます。

@scope (.section1) to (.section2) {
  h2 {
    color: red;
  }
}

このようにtoを使うと.section1要素の中の.section2までの間の要素にだけスタイルが適用されます。

.section2の中の要素にはスタイルが適用されないから注意してね!

実際にChromeブラウザーで結果を見てみましょう。

.section2の中のh2にはスタイルが適用されていないことがわかりますね。

これを@scopeを使わずに書くと以下のようになります。

.section1 h2 {
  color: red;
}
/* .section2 h2のスタイルはリセットする必要がある */
.section2 h2 {
  color: black;
}

今までのCSSでもできなくはないのですが、
このように、スタイルを.section2 h2ではリセットする必要があります。
今までの方法だと、.section1の中の.section2までの間の要素にだけスタイルを適用するのはかなり面倒ですよね。

CSS Nestingとの違い

@scopeに似たような機能として、今後各ブラウザーに実装される予定のCSS Nestingという機能もあります!

これはSassのようにネストしたCSSを書くことができるようになる機能です。

main {
  section {
    h2 {
      color: red;
}
  }
}

これは以下のようなCSSを書いたのと同じ意味になります。

main section h2 {
  color: red;
}

@scopeと同じように決められた要素の中だけにスタイルを適用できるという意味では似ていますね!

では、CSS Nestingと@scopeの違いは何でしょうか?

スコープの範囲を指定できる

やはり先ほど紹介したようにスコープの範囲をtoを使って指定できることが大きな違いです。
CSS NestingだけではネストしたCSSを書くことができるだけで、スコープの範囲を指定することはできません。

すなわち、CSSの構造化にはCSS Nestingを、CSSの適用範囲を指定するには@scopeを使うという使い分けが良いでしょう。

距離の近さで優先度を決定できる

さらに@scopeではスコープ同士でのCSSの優先度の決定方法に決まりがあります。
それは、スコープの距離が近いほど優先度が高くなるというものです。

以下のHTMLを考えます。

<body>
  <main>
    <h2>タイトル</h2>
  </main>
</body>

二つのCSSをみてみましょう。

@scope (main) {
  h2 {
    color: red;
  }
}

@scope (body) {
  h2 {
    color: blue;
  }
}

この時、mainの中にあるh2は何色になるでしょうか?
答えはredです。

これはmainの中にあるh2mainからの距離が1で、bodyからの距離が2だからです。

@scopeにより近い距離にあるスコープのCSSが優先されるということですね。

つまり@scopeはCSS Nestingだけでは実現できない、スコープの距離によっても優先度を決定できます。

似たような機能ですが、違いを理解してより効率的にCSSを書いていきましょう。

CSS Nestingと@scopeは互いに併用できる

先ほどはCSS Nestingと@scopeの違いについて説明しましたが、
CSS Nestingと@scopeはどちらか一方を選ばないといけないわけではありません。
以下のように互いに併用することもできます。

@scope (.card) to (header) {
  :scope {
    inline-size: 40ch;
    aspect-ratio: 3/4;
    > header {
      border-block-end: 1px solid white;
  }
}
}

このように、@scopeでCSSの適用範囲を絞りつつ、CSS NestingでCSSを簡潔に書くこともできます。

@scopeもCSS NestingもCSSをわかりやすく書く素晴らしい機能です!

早く全てのブラウザーでこれらの機能がサポートされることを筆者は願っています!

Authored by

筆者の写真

Godai@steelydylan

Webサービスを作るのが好きなWebエンジニア。子供が産まれたことをきっかけに独立し法人化。サービス開発が大好き。
好きな言語はTypeScript。

サイトの模写でプロを目指す
オンライン学習サービスを作りました!

詳しくはこちら
mosya

mosyaはオンラインでWeb制作を自学習できるサービスです。現役エンジニアが作成した豊富なカリキュラムに沿って学習を進めましょう。

© 2023 - mosya. All rights reserved.