はじめに
この記事は、「うぇーん、CSSのスタイルがなんか上書きされちゃて、どのクラスが当たっているのかわかんないよぉ」と嘆くみなさんに送ります。この記事の半分は優しさでできています。
難しいですよね、CSS。多くのフロントエンドエンジニアの方でも、CSSは誤魔化しで生きています。特に、どのクラスが当たっているかわからなくなりますよね。margin設定しているのに指定通りのmarginにならなかったり、font-sizeが指定した通りにいかなかったり。
そんなあなたに朗報です。CSSに新たな機能が追加されました!それが、@ layer と @ scopeです!この機能を駆使すれば、優先度を自由自在に操れます。これでもう、「どのスタイルが効いているかわからない」とか、「とりあえず!importantにしまくったらどれが優先されているかわからなくなっちゃった」というのもおさらばです。
※@ scopeに関しては2023年時点では、ChromeおよびEdgeのみ利用可能なプロパティです。
@ layerとは
@ layer、カスケードレイヤーとは、簡単に説明すると、CSSのスタイル群を一つのレイヤーにしてしまうという画期的な技術です。
例えば、以下のようなスタイルがあるとします。
.card {
width: 300px;
margin-left: 16px;
margin-right: 16px;
background-color: white;
}
.title {
font-size: 20px;
font-color: #333;
font-weight: bold;
line-height: 24px;
}
通常のスタイルですね。これをカスケードレイヤーにすると、こうなります。
@layer hoge {
.card {
width: 300px;
margin-left: 16px;
margin-right: 16px;
background-color: white;
}
.title {
font-size: 20px;
font-color: #333;
font-weight: bold;
line-height: 24px;
}
}
というような形になります。ただ単に、@layer レイヤー名
で囲ってあげるだけです。何も難しいことはありません。これで囲ってあげるだけで、この場合だったらhoge
というレイヤーになります。
レイヤーにすると何が嬉しいのか
レイヤーになるってことまではわかったけど、じゃあレイヤーにすると何が嬉しいのか。それは、レイヤー同士で優先度を決められるということです。例えば、デフォルトではbutton
やinput
は、元々のスタイルをリセットして、自分でカスタマイズしたスタイルにしたいと言う時、こんな感じになります。
@layer reset,base
@layer reset {
button {
padding: 0;
margin: 0;
font: inherit;
color: inherit;
background: none;
border: none;
}
input {
padding: 0;
margin: 0;
font: inherit;
color: inherit;
background: none;
border: none;
}
}
@layer base {
button {
font-weight: bold;
font-size: 14px;
color:white;
background-color:blue;
}
input {
font-size: 14px;
border: solid 1px yellow;
}
}
この使い方が、@ layerで最も重要な部分です。 使い方としては、今回reset
とbase
という二つのレイヤーがあります。二つ以上ある場合、@layer reset,base
と並べることによって優先度が決められちゃいます。右側にいけば優先度が高くなります。この並べ方によって優先度が決められるので、他のレイヤーを増やしたとしても、この並び順さえ変えてしまえば優先度を好きに決められます。非常にすばらしいですね。外部ファイルのCSSに関しても,@import url("style2.css") layer fuga
のように@import
構文を使えばレイヤー化できます。
ただしレイヤー化されていないスタイルは一番優先度が高い
レイヤー化されいないスタイルは、最も優先度が高くなります。これを逆手に取れば、リセットCSSなど優先度を低くしたいものに関してはレイヤー化させれば低くできます。そして個別にちょっとあてたいスタイルがあれば、別にレイヤー化していなくても優先度が高く設定されます。
例えば、CSS in JS
を使っている場合、細かいスタイルをレイヤー化するのは難しいので、大枠だけレイヤー化させて、細かいスタイルはそのまま書けば思い通りにスタイルを当てられます。
以上が @layer
のご紹介でした。
適用範囲を狭められる@scope
こちらは、CSSの適用範囲を限定できるという画期的なCSSの新しいプロパティです。
今までだと、それぞれのクラスにスタイルを当てるために、CSS in JS
を使ったり、BEM記法
などのCSS設計を行ったりしてクラス名が一意になるように頑張らなければいけませんでした。クラス名がバッティングしてしまと、どこで定義したスタイルが適用されているのかわからなくてってしまうからです。
それが、@scope
を使うと、スタイルの適用範囲を制限できるため、あちらこちらにスタイルが適用されてしまうという事故が防げるんです!
使い方
大まかなコンポーネントに一意的なクラス名を与えてあげます。大まかなコンポーネントとは、<main>~</main>
や、<div>~</div>
など、そのページやなんらかのパーツ全体のことを指しています。
そして、 @scope
を適用してあげます。
@scope (.container) {
:scope {
margin-inline: 8px;
background: #f6f8fa;
}
p {
font-size: 14px;
line-height: 16px;
}
h2 {
font-size: 16px;
line-height:18px;
}
}
ポイントは、適用範囲を制限したいトップに、一意のクラス名を当てて、@scope (クラス名)
で中身を定義してあげるところです。これで、例えばこの例だったら.container
より外にはこのスタイルは適用されません。無駄に大変なクラス名を考える必要も、乱数でクラス名を生成する必要もありません。ちなみに、この:scope
は、そのスコープ内での:root
と同じ意味です。そのクラス内にのみ適用されます。
クラス名の命名規則に関しては自由ですが、ここだけはバッティングしてはいけません。そうすると@scope
の意味がないですから。自分としての提案は、ページ名やコンポーネント名は絶対にバッティングすることがないので、その名前のクラス名を与えてあげればいいと思います。
あまりに細かく@scope
を当てると、@scope
を使っている意味がないので、なるべく大きく使いましょう。
近接度のおかげで、@scope
内のクラスに@scope
を書いても大丈夫
例えば、.container
クラスの中に.card
があって、その中はフォントサイズを小さくして、色も変えたいというとき、その.card
にも@scope
を適用してあげましょう。
@scope (.container) {
/* 略 */
}
@scope (.card) {
p {
font-size:12px;
}
}
このようにしてあげます。HTMLとしては以下のようになっていますね。
<div class="container">
<div class="card">
...
</div>
</div>
これをみてあれって思うかもしれません。「結局、.container
の中に.card
があったら何が適用されるのかわからなくなるじゃん」と。
しかしそれは心配ご無用。@scope
には、近接性という、近い方の@scope
のスタイルが適用されるというルールがあります。これによって、.card
内は.card
のscopeで定義されたスタイルが優先されます。これで心配せずに@scope
でスタイルを定義できますね。
そこだけはスタイルを当てないってこともできる
例えば、.container
のスコープにたくさんスタイルを当てたけど、.hoge
内だけはそれをすべて避けたい時、.hoge
に@scope
を当てて全部打ち消した上でスタイルを当てるということも可能ですが、その.hoge
だけはスタイルを当てないみたいなこともできます。
@scope (.container) to (.hoge) {
/* 何かしらのスタイル */
}
と書くと、.hoge
だけはスタイルが適用されなくなります。この書き方をドーナツスコープと呼びます。ドーナツみたく間をあけてスタイルを当ててるからですね。部分的にスタイルを避けたいときにとても便利です。またあまりに多くドーナツスコープを当てたいときは、そもそも共通化すべきでないものが共通化されているので、見直してあげましょう。そしてその避けたい部分にちゃんと@scope
を当ててあげましょう。
終わりに
いかがでしたでしょうか。CSSの機能が信じられないくらいに進化しました。@scope
は出てきたばかりの機能で対応ブラウザもまだ少ないですが、間違いなくこれから絶対必須の機能です。
今までJavaScriptを駆使しないとできなかったようなことがCSSだけでかなりできるようになりました。みなさんもぜひ、@layer
と@scope
を使ってみてください!
途中で書いてて気づきましたが、QiitaのCSSのコードハイライトがちゃんとat ruleに適用されましたね。