CSS NestingのサポートでネイティブなCSSでネスト構造が書ける



Sassで記述していくことができたネスト構造ですが、WebブラウザでのCSS Nestingのサポートが進み、主要ブラウザではChrome 112、Edge 112、Firefox 117、Safari 16.5以降から、ネイティブなCSSでネスト構造を書くことができるようになります。

ネスト構造(入れ子)は、セレクタの構造がわかりやすく効率よく記述でき、同じセレクタ名を何回も書く必要もなくなるので、これまでのCSSよりスマートに書いていくことができます。

以下、ブラウザのサポート状況になります。

Can I use(CSS Nesting)
https://caniuse.com/?search=CSS%20Nesting

今後、多くのWebブラウザでサポートされるようになれば、快適にCSSを書いていけることでしょう。

ここからは、ネイティブなCSSでのネスト構造の書き方についてご紹介していきます。

CSSのネスト構造の書き方


ネイティブなCSSでのネスト構造について、簡単なサンプルで確認していきます。

まずはHTMLから。
見出しや文章、テキストリンクなどのシンプルなHTML構造を構築してみました。

HTML

<div class="content-block odd">
  <h2>Headline</h2>
  <p>sample text. sample text. sample text. sample text. sample text. sample text. sample text. sample text. sample text. </p>
  <a href="">TextLink</a>
</div>

<div class="content-block even">
  <h2>Headline</h2>
  <p>sample text. sample text. sample text. sample text. sample text. sample text. sample text. sample text. sample text. </p>
  <a href="">TextLink</a>
</div>



続いてはCSS。
ブロックコンテンツのスタイルの記述の後、見出しやテキストリンクなどのスタイルをネスト構造で記述していきます。

CSS

body {
  background-color: #ddd;
}

.content-block {
  width: calc(100% - 1.875rem);
  max-width: 800px;
  margin: 1.875rem auto;
  padding: 1.875rem;
  background-color: #fff;
  &.even {
    background-color: #e9e4ff;
  }
  & h2 {
    font-size: 1.75rem;
    margin: 0 0 1rem;
  }
  & a {
    transition: all .5s ease;
    &:hover {
      color: #f00;
    }
  }
}



Sassでは要素セレクタをそのままネストで書いていけましたが、CSSのネスト構造では「&」や「>」を前に記述してから要素セレクタを指定します。
CSSクラスや擬似クラス、擬似要素も「&」で要素セレクタに連結できます。

サポートされているブラウザでは、以下のようにスタイルが適応されます。

CSSのネスト構造で実装するスタイルの適応



ご利用のテキストエディタによっては、まだ新しい記述に対応していないことがあり、ちょっとしたエラーが表示される場合もありますが、サポートされているWebブラウザでの実装は問題ありません。

また、Google Chrome 120、Safari 17.2、Firefox 117以降のバージョンのWebブラウザからは、ネスト構造のセレクタ指定が「&」を利用せず簡単に書けるようになります。
ChromiumベースのMicrosoft Edgeもすぐにサポートされるでしょう。

以下のように記述していくことができます。

.content-block {
  ...
  ...
  &.even {
    ...
    ...
  }
  h2 {
    ...
    ...
  }
  a {
    ...
    ...
    &:hover {
      ...
      ...
    }
  }
}



ただ、要素セレクタの連結では、もとの要素を参照するために「&」を必要とします。

メディアクエリやコンテナクエリの記述


メディアクエリやコンテナクエリはそのままネストできます。

CSS

body {
  background-color: #ddd;
}

.content-block {
  width: calc(100% - 1.875rem);
  max-width: 800px;
  margin: 1.875rem auto;
  padding: 1.875rem;
  background-color: #fff;
  container-type: inline-size;
  &.even {
    background-color: #e9e4ff;
  }
  & h2 {
    font-size: 1.75rem;
    margin: 0 0 1rem;
    @media (min-width:920px) {
      color: #e56618;
    }
    @container (min-width: 500px) {
      font-size: 2.25rem;
    }
  }
  & a {
    transition: all .5s ease;
    &:hover {
      color: #f00;
    }
  }
}



上記のコードでは、見出しをデバイス幅やコンテンツ幅で調整しています。
@規則(@ルール)はそのまま記述でき、直上の親要素に対する指定となります。

BEM記法でのSassとの違い


CSSの命名規則において、BEM記法で書き慣れている方はつまずくかもしれませんが、BEMでのElementやModifierで繋ぐセレクタの指定では「&」で連結できません。
例として、以下のように記述して確認してみましょう。

HTML

<nav class="header-nav">
  <ul class="header-nav__list">
    <li class="header-nav__item"><a class="nav-link" href="/">Home</a></li>
    <li class="header-nav__item"><a class="nav-link" href="/about.php">About</a></li>
    <li class="header-nav__item"><a class="nav-link" href="/service.php">Service</a></li>
    <li class="header-nav__item"><a class="nav-link" href="/service/education.php">Education</a></li>
    <li class="header-nav__item"><a class="nav-link" href="/service/edu/programming.php">Programming</a></li>
    <li class="header-nav__item header-nav__item--contact"><a class="nav-link" href="/contact.php">Contact</a></li>
  </ul>
</nav>

CSS

.header-nav {
  &__list {
    list-style: none;
    padding: 0 0 0 2rem;
  }
}



BEM記法に合わせた効率的なSassの書き方として、「&」で連結すれば同じBlock名を記述する必要はありませんが、ネイティブCSSのネスト構造では使えません。
ですのでもし、ネイティブCSSで書いていくことがある場合は、以下のように記述していくことになります。

.header-nav {
  & .header-nav__list {
    list-style: none;
    padding: 0 0 0 2rem;
  }
}



BEM記法にも対応してもらえると嬉しいのですが、まだまだ先ですかね。

以下、ここまでの実装結果です。
動画(2分40秒ほど)

まとめ


まだサポートされていないWebブラウザも多くありますので、すぐには利用していくことはできないと思いますが、今後のサポート状況に合わせて、ネイティブなCSSもスマートに記述できるネスト構造で書いていくことが増えると思いますので、記述方法を覚えておくと良いでしょう。