CSS ネスト

お気に入りの CSS プリプロセッサ機能の一つが言語に組み込まれました。ネスト スタイル ルールです。

Adam Argyle
Adam Argyle

ネストする前に、すべてのセレクタを互いに個別に明示的に宣言する必要がありました。その結果、繰り返し、スタイルシートが大量に生成され、作成エクスペリエンスが分散してしまいます。

適用前
.nesting {
  color: hotpink;
}

.nesting > .is {
  color: rebeccapurple;
}

.nesting > .is > .awesome {
  color: deeppink;
}

ネストした後、セレクタを続行して、それに関連するスタイルルールをグループ化することができます。

適用後
.nesting {
  color: hotpink;

  > .is {
    color: rebeccapurple;

    > .awesome {
      color: deeppink;
    }
  }
}

ブラウザで試してみる

ネストにより、デベロッパーはセレクタを繰り返す必要性が減り、関連する要素のスタイルルールを同じ場所に配置できます。ターゲットとする HTML にスタイルを合わせるのにも役立ちます。前の例の .nesting コンポーネントがプロジェクトから削除されている場合は、関連するセレクタ インスタンスのファイルを検索する代わりに、グループ全体を削除できます。

ネストのメリット: - 組織 - ファイルサイズの削減 - リファクタリング

準備課程は Chrome 112 以降で利用できます。また、Safari テクニカル プレビュー 162 で試すこともできます。

CSS ネストのスタートガイド

この投稿の残りの部分では、次のデモ サンドボックスを使用して、選択内容を可視化します。このデフォルトの状態では、何も選択されず、すべてが表示されます。さまざまな形状とサイズを選択することで、構文を練習して動作を確認できます。

大小の円、三角形、正方形のカラフルなグリッド。

サンドボックスの内側には、円、三角形、四角形があります。小、中、大のものがありますその他は青、ピンク、紫色です。これらはすべて、要素を含む .demo 内にあります。以下は、ターゲットにする HTML 要素のプレビューです。

<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 をネストすると、別のセレクタのコンテキスト内で要素のスタイルを定義できます。

.parent {
  color: blue;

  .child {
    color: red;
  }
}

この例では、.child クラスセレクタ.parent クラスセレクタ内にネストされています。つまり、ネストされた .child セレクタは、.parent クラスを持つ要素の子要素にのみ適用されます。

この例では、& 記号を使用して、親クラスの配置場所を明示的に示すこともできます。

.parent {
  color: blue;

  & .child {
    color: red;
  }
}

これら 2 つの例は機能的に同等です。この記事では、より高度な例を説明するにつれて、オプションがある理由がより明確になります。

円の選択

この最初の例では、デモ内の円のみをフェードおよびぼかしるスタイルを追加します。

ネストなしの場合、現在の CSS は次のようになります。

.demo .circle {
  opacity: .25;
  filter: blur(25px);
}

ネストを使用する場合、次の 2 つの方法があります。

/* & is explicitly placed in front of .circle */
.demo {
  & .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

または

/* & + " " space is added for you */
.demo {
  .circle {
    opacity: .25;
    filter: blur(25px);
  }
}

結果.circle クラスの .demo 内のすべての要素がぼかし加工され、ほとんど見えなくなります。

カラフルなグリッドに円が表示されなくなり、背景が薄くなります。
デモを試す

任意の三角形と正方形を選択する

このタスクでは、複数のネストされた要素(グループ セレクタとも呼ばれる)を選択する必要があります。

ネストなしの場合、現在の CSS には次の 2 つがあります。

.demo .triangle,
.demo .square {
  opacity: .25;
  filter: blur(25px);
}

または、:is() を使用します。

/* grouped with :is() */
.demo :is(.triangle, .square) {
  opacity: .25;
  filter: blur(25px);
}

ネストを使用するには、次の 2 つの方法があります。

.demo {
  & .triangle,
  & .square {
    opacity: .25;
    filter: blur(25px);
  }
}

または

.demo {
  .triangle, .square {
    opacity: .25;
    filter: blur(25px);
  }
}

結果.demo 内には .circle 要素のみが残ります。

カラフルなグリッドに残されたのは円のみで、その他の図形はほぼ見えません。
デモを試す

大きな三角形や円を選択する

このタスクには複合セレクタが必要です。複合セレクタの要素が選択されるには、両方のクラスが存在する必要があります。

ネストなしの場合、現在の CSS は次のようになります。

.demo .lg.triangle,
.demo .lg.square {
  opacity: .25;
  filter: blur(25px);
}

または

.demo .lg:is(.triangle, .circle) {
  opacity: .25;
  filter: blur(25px);
}

ネストを使用するには、次の 2 つの方法があります。

.demo {
  .lg.triangle,
  .lg.circle {
    opacity: .25;
    filter: blur(25px);
  }
}

または

.demo {
  .lg {
    &.triangle,
    &.circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

結果、すべての大きな三角形と円が .demo 内に非表示になります。

カラフルなグリッドでは、小型と中程度の図形しか見えません。
デモを試す
複合セレクタとネストに関する上級者向けのヒント

ここでは、ネストされたセレクタに隣接させる方法を明示的に示しているため、& 記号が有用です。たとえば次のようになります。

.demo {
  .lg {
    .triangle,
    .circle {
      opacity: .25;
      filter: blur(25px);
    }
  }
}

ネストには有効な方法ですが、結果は期待する要素とは一致しません。これは、組み合わせた .lg.triangle, .lg.circle の望ましい結果を & で指定しない場合、実際の結果は .lg .triangle, .lg .circle(つまり子孫セレクタ)となるためです。

ピンク色の図形を除くすべての図形を選択しています

このタスクでは、否定関数疑似クラスが必要です。ここで、要素にセレクタを指定することはできません。

ネストなしの場合、現在の CSS は次のようになります。

.demo :not(.pink) {
  opacity: .25;
  filter: blur(25px);
}

ネストを使用するには、次の 2 つの方法があります。

.demo {
  :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

または

.demo {
  & :not(.pink) {
    opacity: .25;
    filter: blur(25px);
  }
}

結果、ピンク以外のすべてのシェイプが .demo 内に非表示になります。

カラフルなグリッドがモノクロになり、ピンクの図形のみが表示されています。
デモを試す
& による精度と柔軟性

:not() セレクタで .demo をターゲットにしたいとします。そのためには、&必須です。

.demo {
  &:not() {
    ...
  }
}

上記の例では .demo :not() が必要でしたが、.demo:not().demo:not() になります。このリマインダーは、:hover インタラクションをネストする場合に非常に重要です。

.demo {
  &:hover {
    /* .demo:hover */
  }

  :hover {
    /* .demo :hover */
  }
}

その他のネスト例

ネストの CSS 仕様には、他にもさまざまな例があります。サンプルを通じて構文の詳細を確認する場合は、有効な例と無効な例を幅広く取り扱っています。

次のいくつかの例では、CSS ネスト機能を簡単に紹介し、その機能の幅広さを理解するのに役立ちます。

@media のネスト

スタイルシートの別の領域に移動してセレクタとそのスタイルを変更するメディアクエリ条件を見つけると、混乱を招く可能性があります。コンテキスト内で条件をネストできれば、気を散らす要因がなくなります。

構文の便宜上、ネストされたメディアクエリで現在のセレクタ コンテキストのスタイルのみを変更する場合は、最小限の構文を使用できます。

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    font-size: 1.25rem;
  }
}

& を明示的に使用することもできます。

.card {
  font-size: 1rem;

  @media (width >= 1024px) {
    &.large {
      font-size: 1.25rem;
    }
  }
}

この例では、& で拡張された構文を示しています。また、.large カードをターゲットにして、追加のネスト機能が引き続き動作することを示しています。

詳しくは、@rules のネストをご覧ください。

ネストできる場所

ここまでの例はすべて、前のコンテキストに継続されているか、前のコンテキストに追加されています。必要に応じて、コンテキストを完全に変更または並べ替えることができます。

.card {
  .featured & {
    /* .featured .card */
  }
}

& 記号は、文字列ではなくセレクタ オブジェクトへの参照を表し、ネストされたセレクタ内の任意の場所に配置できます。複数回配置することもできます。

.card {
  .featured & & & {
    /* .featured .card .card .card */
  }
}

この例は少し役に立たないようですが、セレクタ コンテキストを繰り返すと便利なシナリオもあります。

無効なネストの例

プリプロセッサでネストしている場合は、予期しないネスト構文のシナリオがいくつかあります。

ネストと連結

CSS クラスの多くの命名規則では、セレクタを文字列のように連結または追加できるネストが重要になります。セレクタは文字列ではなくオブジェクト参照であるため、CSS のネストではうまくいきません。

.card {
  &--header {
    /* is not equal to ".card--header" */
  }
}

詳しくは、仕様をご覧ください。

厄介なネストの例

セレクタリストと :is() 内でのネスト

次のような CSS ブロックをネストする場合を考えてみましょう。

.one, #two {
  .three {
    /* some styles */
  }
}

これはセレクタリストで始まり、さらにネストする最初の例です。これまでの例はセレクタリストでのみ終了していました。このネスト例に無効なものはありませんが、セレクタリスト(特に ID セレクタを含むリスト)内のネストについては、実装の詳細が複雑になる可能性があります。

ネストのインテントが機能するように、最も内側のネストではないセレクタリストは、ブラウザによって :is() でラップされます。このラッピングにより、作成されたコンテキスト内でセレクタリストのグループ化が維持されます。このグループ化 :is(.one, #two) の副作用は、かっこ内のセレクタ内で最高スコアの特異性が適用されることです。:is() は常にこのように機能しますが、ネスト構文を使用すると、作成されたものとは一致しないので驚くかもしれません。要点をまとめます。ID とセレクタ リストをネストすると、非常に高い特異性セレクタにつながる可能性があります。

厄介な例をわかりやすくまとめると、次のように前のネスト ブロックがドキュメントに適用されます。

:is(.one, #two) .three {
  /* some styles */
}

ID セレクタを使用しているセレクタリスト内でネストする場合、そのセレクタリスト内のすべてのネストの特異性が高くなるので、注意深く観察するか、リンターに警告するように指示してください。

ネストと宣言の混在

次のような CSS ブロックをネストする場合を考えてみましょう。

.card {
  color: green;
  & { color: blue; }
  color: red;
}

.card 要素の色は blue になります。

混合したスタイル宣言は、ネストが発生する前に作成されたかのようにトップにホイスティングされます。詳細については、仕様をご覧ください。

これを回避する方法はあります。以下の例では、3 つのカラースタイルを & でラップしています。これにより、作成者が意図したとおりにカスケードの順序が維持されます。.card 要素の色は赤になります。

.card {
  color: green;
  & { color: blue; }
  & { color: red; }
}

実際、ネストの後に続くスタイルはすべて & でラップすることをおすすめします。

.card {
  color: green;

  @media (prefers-color-scheme: dark) {
    color: lightgreen;
  }

  & {
    aspect-ratio: 4/3;
  }
}

機能検出

CSS のネストの機能を検出するには、ネストを使用する方法と、@supports を使用してネストセレクタの解析機能を確認する方法の 2 つがあります。

ブラウザが CSS ネストをサポートしているかどうかを尋ねている Bramus Codepen のデモのスクリーンショット。その質問の下には緑色のボックスがあり、サポートしていることを示します。

ネストを使用する場合:

html {
  .has-nesting {
    display: block;
  }

  .no-nesting {
    display: none;
  }
}

使用中: @supports

@supports (selector(&)) {
  /* nesting parsing available */
}

同僚の Bramus がこの戦略について説明している優れた Codepen です。

Chrome DevTools によるデバッグ

現在のところ、DevTools のネストのサポートは最小限です。現時点では、スタイルは [スタイル] ペインに想定どおりに表示されますが、ネストとその完全なセレクタ コンテキストのトレースはまだサポートされていません。Google では これを透明かつ明確に するための設計と計画があります

Chrome DevTools のネスト構文のスクリーンショット。

Chrome 113 では、CSS のネストに対する追加サポートが予定されています。最新情報を随時ご確認ください。

今後の計画

CSS ネストはバージョン 1 のみです。バージョン 2 では、より多くの糖衣構文が導入され、記憶するルールが少なくなる可能性があります。ネストの解析に制約を設けたり、処理に注意を要する瞬間を持たせたりしないことは、大きな要件です。

ネストは、CSS 言語の大きな機能強化です。これは CSS のほぼすべてのアーキテクチャ要素に オーサリングに影響を及ぼしますバージョン 2 を効果的に指定する前に、この大きな影響を詳細に調査して理解する必要があります。

最後に、@scope、ネスト、@layer をすべて一緒に使用するデモをご覧ください。みんな、とてもワクワクするわ!

グレーの背景に明るいカード。このカードには、タイトルとテキスト、いくつかの操作ボタン、サイバーパンク スタイルの画像が表示されています。