CSS ネスト

CSS プリプロセッサの人気機能の 1 つであるスタイルルールのネスト機能が、言語に組み込まれました。

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 内のすべての要素がぼやけて、ほとんど見えなくなります。

カラフルな図形のグリッドに円がなくなり、背景に非常に薄く表示されます。
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);
  }
}

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

カラフルな図形のグリッドに残っているのは円のみで、他の図形はほとんど見えません。
Demo を試す

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

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

ネストなしの場合、現在の 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 を試す
複合セレクタとネストに関する上級者向けのヒント

ネストされたセレクタを結合する方法が明示的に示されているため、ここでは & 記号が役に立ちます。たとえば次のようになります。

.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 内に隠されます。

カラフルなグリッドがモノクロになり、ピンクの形状のみが表示されるようになりました。
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 つの方法があります。

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

ネストを使用する:

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 をすべて使用するデモを紹介します。みんな、とてもワクワクするわ!

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