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 コンポーネントがプロジェクトから削除されている場合、関連するセレクタ インスタンスのファイルを検索する代わりに、グループ全体を削除できます。

ネストが役立つ理由: - 組織化 - ファイルサイズの削減 - リファクタリング

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 つの例は機能的には同じです。この 2 つのオプションがある理由は、この記事ではより高度な例を追って説明していきます。

円を選択する

この最初の例では、スタイルを追加してデモ内の円だけをフェードし、ぼかします。

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

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

ネストの場合、有効な方法は 2 つあります。

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

or

/* & + " " 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);
  }
}

or

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

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

シェイプのカラフルなグリッドは円のみを残し、他のシェイプはすべてほとんど見えない。
デモを試す

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

このタスクには複合セレクタが必要です。複合セレクタでは、要素を選択するには両方のクラスが必要です。

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

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

or

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

ネストの場合、有効な方法は 2 つあります。

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

or

.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);
  }
}

or

.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 でのネストのサポートは最小限にとどまっています。現時点では、[Styles] ペインにはスタイルが想定どおりに表示されますが、ネストとその完全なセレクタ コンテキストのトレースはまだサポートされていません。これを透明性と明確化したデザインと計画があります

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

Chrome 113 では、CSS のネストのサポートが追加される予定です。今後の情報にご注目ください。

今後の計画

CSS Nesting はバージョン 1 のみです。バージョン 2 では、導入する糖衣構文が多く、記憶するルールが少なくなる可能性があります。ネストの解析は、制限を受けないようにすることや、難しい場面が大いに求められています。

ネストは、CSS 言語の大幅な機能強化です。CSS のほとんどすべてのアーキテクチャ面に 影響がありますバージョン 2 を効果的に指定するには、この大きな影響を十分に調査して理解する必要があります。

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

グレーの背景に描かれたライトカード。カードには、タイトルとテキスト、いくつかの操作ボタン、サイバーパンク風の画像が含まれています。