CSSのネストがついにブラウザで使用できるようになった! 基礎知識、便利な使い方を詳しく解説
Post on:2023年4月19日
CSSのネストがついに、Chrome 112, Edge 112にサポートされました。
追記: 2023/8/29リリース予定のFirefox 117でもサポート予定。
ネストはSassなどのCSSプリプロセッサですでに使用している人も多いと思いますが、CSSのネストは仕様が少し異なります。とは言え、CSSでネストが使用できるようになるのは、嬉しいことですね。
CSSのネストの基礎知識、便利な使い方を紹介します。ネストの使い方を学べるデモページもあるので、勉強するのにぴったりです。
CSS Nesting
by Adam Argyle
下記は各ポイントを意訳したものです。
※元サイト様のライセンスに基づいて翻訳しています。
CSSのネストとは
わたし達のお気に入り、CSSプリプロセッサの機能の1つであるスタイルルールのネスト(入れ子)が言語として組み込まれました。ネストの仕様はCSS Nesting Moduleです。
CSSでネストを使用できる前は、すべてのセレクタを互いに個別に明示的に宣言する必要がありました。これにより繰り返しが多くなってしまい、スタイルシートがかさばり、オーサリングのエクスペリエンスが散漫でした。
1 2 3 4 5 6 7 8 9 10 11 |
.nesting { color: hotpink; } .nesting > .is { color: rebeccapurple; } .nesting > .is > .awesome { color: deeppink; } |
ネストを使用できる後は、セレクタを継続し、それに関連するスタイルルールをグループ化することができます。
1 2 3 4 5 6 7 8 9 10 11 |
.nesting { color: hotpink; > .is { color: rebeccapurple; > .awesome { color: deeppink; } } } |
実際の動作は、デモページでご覧ください。
See the Pen
Nesting is awesome example by web.dev (@web-dot-dev)
on CodePen.
CSSのネストとは、セレクタを繰り返す必要性を減らし、関連する要素のスタイルルールを同じ場所に配置することで、デベロッパーを支援します。また、スタイルが対象とするHTMLに一致するようにすることもできます。上記の例の.nesting
コンポーネントがプロジェクトから削除された場合、関連するセレクタをファイル検索する代わりに、グループ全体を簡単に削除できます。
CSSのネストは、次のことに役立ちます。
- CSSの組織化
- ファイルサイズの軽量化
- リファクタリング
CSSのネストはChrome 112, Edge 112から利用でき、Safariも次の16.5でサポートされる予定です。
追記: 2023/8/29リリース予定のFirefox 117でもサポート予定。
CSSのネストの基礎知識
この記事の残りの部分では、内容を視覚化するためにデモのサンドボックスを用意しました。デフォルトの状態では何も選択されておらず、すべてが表示されています。さまざまな形やサイズを選択することで、ネストの構文を練習し、動作を確認できます。
サンドボックスには、丸・三角形・四角形の形があります。大きさは小・中・大、カラーはブルー・ピンク・パープルです。これらはすべて.demo
を含む要素内にあります。
HTMLは、下記のようになっています。
1 2 3 4 5 6 7 8 9 |
<div class="demo"> <div class="sm triangle pink"></div> <div class="sm triangle blue"></div> <div class="square blue"></div> <div class="sm square pink"></div> <div class="sm square blue"></div> <div class="circle pink"></div> … </div> |
CSSのネストの例
CSSのネストを使用することで、別のセレクタのコンテキスト内で要素のスタイルを定義できます。
1 2 3 4 5 6 7 |
.parent { color: blue; .child { color: red; } } |
このCSSでは、.child
セレクタが.parent
セレクタ内にネストされています。これはネストされた.childセレクタが.parentクラスを持つ要素の子である要素にのみ適用されることを意味します。
上記のCSSは、親クラスを配置する場所を明示的に示すために&
記号を使用して記述することもできます。
1 2 3 4 5 6 7 |
.parent { color: blue; & .child { color: red; } } |
この2つのCSSは機能的に同等であり、オプションがある理由はこの記事でより高度な例を解説するにつれて明らかになります。
円を選択してみましょう。
最初のタスクは、スタイルを追加してデモの円だけをフェードおよびブラーさせることです。
ネストなし: 現在のCSS
1 2 3 4 |
.demo .circle { opacity: .25; filter: blur(25px); } |
ネストあり: これからのCSSには2つの方法があります。
1 2 3 4 5 6 7 |
/* &は明示的に .circleの前に配置します */ .demo { & .circle { opacity: .25; filter: blur(25px); } } |
もしくは、
1 2 3 4 5 6 7 |
/* & + " " スペースが追加されます */ .demo { .circle { opacity: .25; filter: blur(25px); } } |
このCSSを加えると、.demo
内で.circle
クラスを持つ要素はblur(25px)
が適用されてぼやけます。
デモページ(Chrome 112で表示)
三角形と四角形を選択してみましょう。
このタスクは、ネストされた複数の要素(グループセレクタと呼ばれます)を選択する必要があります。
ネストなし: 現在のCSSには2つの方法があります。
1 2 3 4 5 |
.demo .triangle, .demo .square { opacity: .25; filter: blur(25px); } |
もしくは、
1 2 3 4 5 |
/* :is()でグループ化 */ .demo :is(.triangle, .square) { opacity: .25; filter: blur(25px); } |
ネストあり: これからのCSSには2つの方法があります。
1 2 3 4 5 6 7 |
.demo { & .triangle, & .square { opacity: .25; filter: blur(25px); } } |
もしくは、
1 2 3 4 5 6 |
.demo { .triangle, .square { opacity: .25; filter: blur(25px); } } |
ネストしたCSSはどちらも下記のように:is()
を使用することもできます。
1 2 3 4 |
.demo :is(.triangle, .square) { opacity: .25; filter: blur(25px); } |
このCSSを加えると、.demo
内には.circle
要素のみがはっきり見えます。
デモページ(Chrome 112で表示)
大きな三角形と円を選択してみましょう。
このタスクには複合セレクタが必要です。選択するには、要素に両方のクラスが存在する必要があります。
ネストなし: 現在のCSS
1 2 3 4 5 |
.demo .lg.triangle, .demo .lg.square { opacity: .25; filter: blur(25px); } |
もしくは、
1 2 3 4 |
.demo .lg:is(.triangle, .circle) { opacity: .25; filter: blur(25px); } |
ネストあり: これからのCSSには2つの方法があります。
1 2 3 4 5 6 7 |
.demo { .lg.triangle, .lg.circle { opacity: .25; filter: blur(25px); } } |
もしくは、
1 2 3 4 5 6 7 8 9 |
.demo { .lg { &.triangle, &.circle { opacity: .25; filter: blur(25px); } } } |
このCSSを加えると、.demo
内の大きな三角形と円がぼやけます。
デモページ(Chrome 112で表示)
複合セレクタとネストに関する上級テクニック
&
記号はネストされたセレクタに隣接する方法を明示的に示すために活躍します。たとえば、下記のCSSをご覧ください。
1 2 3 4 5 6 7 8 9 |
.demo { .lg { .triange, .circle { opacity: .25; filter: blur(25px); } } } |
ネストする方法としては有効ですが、結果と期待する要素は一致しません。その理由は、.lg.triangle, .lg.circle
を複合させるという期待する結果を&
で指定しないと、実際の結果は.lg .triangle, .lg .circle
という子孫セレクタになるからです。
重要な用語:
&
なしでクラスをネストすると、常に子孫セレクタになります。その結果を変更するには、&
記号を使用します。
ピンク以外の形をすべて選択してみましょう。
このタスクには、要素が指定されたセレクタを持ってはならない否定疑似クラスが必要です。
ネストなし: 現在のCSS
1 2 3 4 |
.demo :not(.pink) { opacity: .25; filter: blur(25px); } |
ネストあり: これからのCSSには2つの方法があります。
1 2 3 4 5 6 |
.demo { :not(.pink) { opacity: .25; filter: blur(25px); } } |
もしくは、
1 2 3 4 5 6 |
.demo { & :not(.pink) { opacity: .25; filter: blur(25px); } } |
このCSSを加えると、.demo
内でピンク以外のすべての形がぼやけます。
デモページ(Chrome 112で表示)
&による精度と柔軟性
たとえば、:not()
セレクタで.demo
をターゲットにしたいとします。そのためには&
が必要です。
1 2 3 4 5 |
.demo { &:not() { ... } } |
これは.demo
と:not()
を.demo:not()
に合成するもので、前のCSSでは.demo :not()
が必要でしたが、このCSSでは.demo:not()
になります。注目すべき点は、:hover
インタラクションをネストさせたいときに非常に重要になるということです。
1 2 3 4 5 6 7 8 9 |
.demo { &:hover { /* .demo:hover */ } :hover { /* .demo :hover */ } } |
その他のCSSのネストの例
CSS Nesting Moduleの仕様には、さらに多くの例が含まれています。ネストをもっと知りたいという人に、有効な例と無効な例が広く取りあげられています。
この記事ではいくつかCSSのネスト機能を簡単に解説し、導入される機能の幅広さを理解できるようにしたいと思います。
@mediaのネスト
セレクタとそのスタイルを変更するメディアクエリ条件を見つけるために、スタイルシートの別の領域に移動することは、非常に気が散ることがあります。しかし、コンテキストの中に条件をネストすることで、その煩わしさを解消できます。
構文の便宜上、ネストされたメディアクエリが現在のセレクタのコンテキストのスタイルだけを変更する場合は、最小限の構文を使用できます。
1 2 3 4 5 6 7 |
.card { font-size: 1rem; @media (width >= 1024px) { font-size: 1.25rem; } } |
&
を明示的に使用することもできます。
1 2 3 4 5 6 7 8 9 |
.card { font-size: 1rem; @media (width >= 1024px) { &.large { font-size: 1.25rem; } } } |
この例では、&
による拡張構文を示すと同時に、.large
をターゲットにして追加のネスト機能が引き続き機能することを示しています。
@rules
のネストについて詳しくは、CSS Nesting Moduleをご覧ください。
どこでもネスト
ここまでの例はすべて、前のコンテキストに継続または追加されています。必要に応じて、コンテキストを完全に変更したり、再配置することができます。
1 2 3 4 5 |
.card { .featured & { /* .featured .card */ } } |
&
記号は(文字列ではなく)セレクタオブジェクトへの参照をあらわし、ネストされたセレクタ内の任意の場所に配置できます。また、複数回配置することもできます。
1 2 3 4 5 |
.card { .featured & & & { /* .featured .card .card .card */ } } |
このCSSは役に立たないように見えるかもしれませんが、セレクタのコンテキストを繰り返し使用できると便利なシナリオが確かにあります。
CSSのネストの無効な例
無効になってしまうネストの構文がいくつかあり、プリプロセッサでネストしている人は驚くかもしれません。有効なネスト構文のチートシートは後述します。
要素タグのネスト
HTML要素は現在のところ、前に&
記号を加えるか、:is()
で内包する必要があります。
1 2 3 4 5 |
.card { h1 { /* 🛑 h1が記号で始まっていない */ } } |
上記のCSSを機能するように修正します。
1 2 3 4 5 6 7 8 9 10 11 |
.card { & h1 { /* ✅ h1を記号で始める */ } /* or */ :is(h1) { /* ✅ :is()で内包する */ } } |
ネストと連結
CSSのクラスの命名規則の多くは、セレクタを文字列であるかのように連結または追加できるネストに依存しています。セレクタは文字列ではなく、オブジェクト参照であるため、これはCSSのネストでは機能しません。
1 2 3 4 5 |
.card { &--header { /* .card--headerと等しくない */ } } |
より詳しくはCSS Nesting Moduleをご覧ください。
ネストと宣言の混在
下記のようなネストされたCSSのブロックをご覧ください。
1 2 3 4 5 |
.card { color: green; & { color: blue; } color: red; } |
.card
要素の色はブルーになります。
混在するスタイル宣言は、ネストが発生する前にオーサリングされたかのように先頭に持ち上げられます。詳しくはCSS Nesting Moduleをご覧ください。
CSSのネストのパーサーについて
CSSのネストを最大限に活用するためには、仕様書を読み込むか、CSSパーサーがネストに対してどのように機能するかを学ぶことです。この知識があれば、ネストのルールをいつも確認することなく、自信を持ってスタイルをネストにできます。
CSSパーサーで最初に学ぶべきことは、ネストのスタイルを使用していることをパーサーに通知するシンボルを覚えておくことです。
1 |
& @ : . > ~ + # [ * |
これらの記号文字は見覚えがあると思います。いくつかはコンビネーターで、いくつかはセレクタ用です。つまり、パーサーがネストしたセレクタを検出したときに、これらの記号文字で始まらない場合はパーサーは失敗し、スタイルを不正に処理します。
これらの記号文字があるかないかで処理をします
CSSのネストを検出する方法
CSSのネストを検出する機能には、ネストを使用する方法と@supports
でネストしたセレクタをチェックする方法があります。
CSSのネストがサポートされているかを検出
ネストを使用する方法
1 2 3 4 5 6 7 8 9 |
html { .has-nesting { display: block; } .no-nesting { display: none; } } |
@supportsを使用する方法
1 2 3 |
@supports (selector(&)) { /* nesting parsing available */ } |
実際の動作はデモページでご確認ください。
デベロッパーツールでCSSのネストをデバッグする方法
デベロッパーツールのネストに関する現在のサポートは、最小限です。スタイルは「スタイル」パネルで期待通りに表示されますが、ネストとその完全なセレクタのコンテキストをトレースすることはまだサポートされていません。わたし達はこれを明確にするための設計と計画があります。
Chrome 113ではさらにサポートする予定です、ご期待ください。
CSSのネストのこれから
2023年現在、CSS Nesting Moduleはバージョン1のみです。バージョン2では、より多くの構文解析が導入され、覚えるべきルールが減る可能性があります。パーサーを起動させるための記号文字のリストを持たないように多くのリクエストがあります。
CSSのネストは、CSS言語を大きく強化する機能です。CSSのほとんどすべてのアーキテクチャの側面に対してオーサリングに影響を与えます。この大きな影響はバージョン2が仕様化される前に、深く理解しておく必要があります。
最後に、@scope
とCSSのネストと@layer
のすべてを使用したデモを紹介します。とてもエキサイティングなものです!
sponsors