LoginSignup
7
0

これまでセレクターの適用範囲を絞るためにはCSSの詳細度を高めることで実現してきたと思います。
詳細度を高めずにセレクターの適用範囲を設定できる@scopeについてまとめます。

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

2023年11月11日時点でのブラウザサポート状況です。

image.png

Chromeの118からサポートされた@scopeは、SafariやFirefoxでは利用できないようなので、気にせず利用できるようになるまでにはもう少しかかりそうです。

@scopeの使い方

使い方は簡単です。
.hogeの子要素にあるspanタグのテキストを赤色にしたい場合は下記のように書きます。

@scope (.hoge) {
  span {
    color: red;
  }
}

@scopeの利点

はじめに記述した通り、CSSの詳細度をあげることなくスタイルを当てることができます。

// 従来の指定:詳細度(0.1.1)
.hoge {
  span {
    color: red;
  }
}

// @scopeを使った場合:詳細度(0.0.1)
@scope (.hoge) {
  span {
    color: red;
  }
}

@scopeで使用したセレクターは詳細度に影響を与えることはありません。
なので@scopeを使って指定したspanタグは下記のclassでも上書きできます!

.blue {
  color: blue;
}

ドーナッツスコープ

初めて聞きましたが、指定した要素の間に設置された要素に対してスタイルを適用する方法のことをドーナッツスコープといいます!(知らんかった…)

@scope (.hoge) to (.hoge-inner) {
  span {
    color: red;
  }
}

:scope擬似クラスについて

擬似クラスを利用することでスコープの対象にしたセレクターに対してスタイルを当てることが可能です!

@scope (.hoge) {
  :scope {
    // .hogeに対してスタイルを当てられる
  }
}

また、対象にした子要素に対してスタイルを当てたい時はいくつか方法があります!

@scope (.hoge) {
  // ①
  span {
    color: red;
  }

  :scope span {
    // .hogeの子要素であるspanにスタイルを当てる「①」と同じ
  }

  & span {
    // .hogeの子要素であるspanにスタイルを当てる「①」と同じ
  }
}

複雑な要件も実現できます!

// :scope直下の子要素である場合に適応させたい場合
@scope (.hoge) to (:scope > .hogehoge) {}

// .hogehoge内に:scopeがある場合に適応させたい場合
@scope (.hoge) to (.hogehoge :scope .hogehoge-inner) {}

ただ、下記のような記述はスコープ内にない要素を指定することになるので無効となります…

@scope (.hoge) {
  :scope + span {
  
  }
}

@scopeの詳細度

@scopeの中で擬似クラスを利用すると詳細度が上がってしまうことは留意しておいてください!

@scope (.hoge) {
  span {
    // 詳細度:(0, 0, 1)
  }
  
  :scope span {
    // 詳細度:(0, 1, 1)
  }
  
  & span {
    /*
      「&」は「is()」糖衣されます
      実際には、:is(.hoge) spanとなります
      詳細度:(0, 1, 1)
    */
  }
}

is()の詳細度の計算には注意が必要です。
is()の詳細度は囲まれたセレクターの中で最も高い詳細度のものが計算の対象となります。

is(#hoge, .hoge) span {}

上記の場合詳細度は、is()の中で最も詳細度が高いのは#hogeなので詳細度は(1,0,0)となり、
詳細度の合計はその後のspanと合わせて(1,0,1)となります。

プレリュードなしのスコープ

プレリュードとは@scopeの後につく()で囲んだ部分のことです。
下記の記述でいうと「.hoge」の部分にあたる箇所です。

@scope (.hoge) {}

プレリュードは<style>タグを利用してHTMLに直接書くことで省略することができます。

<div class="hoge">
  <div class="hogehoge">
    <style>
      @scope {
        color: red;
      }
    </style>
  </div>
</div>

スコープ近接性

CSSのカスケードに新しいステップが追加されました。

image.png
https://developer.chrome.com/articles/at-scope/

これによって同名のclassを入れ子にする場合の制御が便利になりました。

<style>
  .red { color: red; }
  .blue { color: blue; }
  .red span { color: red; }
  .blue span { color: blue; }
</style>
<div class="red">
  <span>hoge</span>
  <div class="blue">
    <span>hoge2</span>
    <div class="red">
      <span>hoge3</span>
    </div>
  </div>
</div>

上記のスタイリングの結果は以下の画像のようになります。

image.png

本来であれば「hoge3」は赤文字になってほしいところですが、カスケードの特性上.blue spanが一番優先されます。

@scopeだと下記のように記述することで上記の問題を解決できます!

<style>
  @scope (.red) {
    :scope { color: red; }
    span { color: red; }
  }
   @scope (.blue) {
    :scope { color: blue; }
    span { color: blue; }
  }
</style>

image.png

まとめ

カスケードの仕組み上、外部スタイルシートの読み込み順や書き順を意識しないといけない場合もありましたが@scopeを利用することでこれまで必要だった思考が必要なくなりそうです!

とはいえまだ最新のブラウザでしか利用できないのでしばらく利用は控えた方が良さそうな印象です。
そもそもReactやVue.jsのようなフレームワークを利用すれば@scopeを使わなくてもスコープを切ってスタイリングができるので実装技術を検討するのも方法かと思います!

プレーンなCSSでスタイルの定義が分離できるのはコードの見通しが良くなり修正のしやすさもUPできるのは良いですね!

参考リンク

7
0
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
0