21
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

ニジボックスAdvent Calendar 2021

Day 5

そろそろ Native CSS Nesting の話をしよう

Last updated at Posted at 2021-12-04

この記事では 2021年8月に公開された CSS Nesting Module の First Public Working Draft について解説します。

3 行でわかる CSS Nesting Module

  • 今年 8/31 に CSS Nesting Module の First Public Working Draft が公開
  • スタイルルールをネストして記述することができ、CSS の可読性と保守性が向上させるのに役立つ
  • 対応ブラウザはまだないが、これから出てきそう!

CSS Nesting Module とは

CSS Nesting Module とは、スタイルルールを入れ子(ネスト)にして記述するための仕様です。
今年 8/31 に CSS Nesting Module の First Public Working Draft が公開され話題になりました(ちなみに Editor's Draft は 2018 年)。
スタイルをネストする記法は古来より Sass や Less などでもお馴染みですが、重複する指定を減らして可読性を高めたり、関連のスタイルをグルーピングすることで保守性を高めたりできるメリットがあります。
ネイティブの CSS でスタイルのネストがサポートされることによって、プリプロセッサを使用せずともこの恩恵を享受できるようになります。

.header {
  background-color: blue;
}
.header p {
  font-size: 16px;
}
.header p a:hover {
  color: green;
}

上記のコードを SCSS や Less などのプリプロセッサを使わずに、このように書くことができます!1

.header {
  background-color: blue;
  & p {
    font-size: 16px;
    & a {
      &:hover {
        color: green;
      }
    }
  }
}

すっげー!🤩

記述方法は 2 種類

ネストしたスタイルの書き方には下記の 2 つがあります。

  • Direct Nesting
  • @nest

Direct Nesting

ネスティングセレクタ & 使う構文で、各プリプロセッサでもお馴染みの記法です。

p {
  color: black;
  .body {
    color: red; //  p.body に適用される
  }
}

↓ ネストの中で隣接セレクタも使用可能

.foo {
  color: blue;

  & + .bar {
    color: red; //  .foo + .bar に適用される
  }
}

↓ メディアクエリもネストできる

.header {
  font-size: 24px;

  @media (max-width: 760px) {
    & {
      font-size: 12px;
    }
  }
}

その他にも Working Draft に豊富な具体例があるので、興味がある方は是非ご覧ください。

Direct Nesting の注意点

Direct Nesting では & は常にセレクタの最初に書かなければないというルールがあります。
つまり、下記のようにセレクタの後ろに & を書いてもうまく解釈されません。

.header {
  background: white;
  .dark & { //← .dark .header に適用されない🤯
    background: blue;
  }
}

このような場合に役に立つのが、次に紹介する @nest を使う構文です。

@nest

@nest を使うことで & を書く位置をもっと柔軟に決めることができます。

.header {
  background: white;
  @nest .dark & { //← .dark .header に適用される
    background: blue;
  }
}

↓ 擬似クラスにも&を使用することができます

.foo {
  color: red;
  @nest :not(&) { // :not(.foo) に適用される
    color: blue;
  }
}

Direct Nesting と @nest は一緒に使える

Direct Nesting と @nest を一緒に使うことで、より複雑なネストの指定が可能になります。

.foo {
  color: blue;
  @nest .bar & {
    color: red;
    &.baz {
      color: green;
    }
  }
}

なぜ @nest が必要なの?

最初から Direct Nesting でだけで書けるようにすればいいじゃない!と思う人もいるかもしれません(私は思いました)。

.header {
  background-color: white;
  .dark & {
    background-color: blue;
  }
}

上記のような書き方を許容してしまうと、テキストが宣言なのかスタイルルールの始まりなのかを判断するために無限に先読みが必要になってしまいます。
例えば、color:hover... という記述をパーサーは color プロパティなのか、<color> 要素なのかその箇所だけで判断することができません。
そのため、& もしくは @nest でセレクタを開始することで、「これはセレクタである」ということをパーサーに伝える必要があるのです。
参考: https://www.w3.org/TR/2021/WD-css-nesting-1-20210831/#:~:text=Why%20can%E2%80%99t%20everything%20be%20directly%20nested%3F

CSS Nesting Module でできないこと

Sass や Lessでは下記のように & を使用して文字列を連結し、BEM のクラス名をセレクタとして楽々指定することができました。

.foo {
  color: blue;
  &__bar {
    color: red;
  }
}

しかし、この書き方でクラス名同士を連結することは、セレクタ構文の仕様に矛盾しているため、__bar は HTML のカスタムエレメントだと解釈されてしまいます。

CSS Nesting Module の注意点

CSS Nesting ではセレクタが解決されると、ブラウザは :is()2 で親セレクタをラップしたセレクタに置き換えて解釈します。

.foo,
.bar {
  color: blue;
  & + .bar {
    color: red;
  }
}

.foo,
.bar {
  color: blue;
}
:is(.foo, .bar) + .baz {
  color: red;
}

:is()と類似の擬似セレクタに :where()3というものもありますが、 :is()だと解釈されるのがポイントです。

:is() を使うと :where() とは違いセレクタ全体の詳細度にカウントされるため、下記の様にネストせずに書いた場合と同じ詳細度になります。

.foo + .baz, .bar + .baz  {
  color: red;
}

つまり、ネストすればするほど詳細度は高くなってしまうということです。
スタイルの上書きに !important を使わざるをえない地獄を味あわないためにも、ネストの使いすぎに注意したいですね。

CSS Nesting Module を使う

ブラウザ自体は未対応ですが、PostCSS を使用することで今からでも Nesting Module を使用できます。

おわりに

これまで見てきた CSS Nesting Module の仕様はまだ Working Draft であるため、今後変更の加わる可能性が大いにあります。
これから順次ブラウザにサポートされることが予想されるため、今後の動向に期待が高まりますね。
しかし、新しい仕様が登場してブラウザがそれをサポートしても、古いブラウザのシェアが高い状態だとなかなか実務では取り入れづらく、もどかしい思いをしている人も多いのではないでしょうか。
全人類が最新ブラウザにアップデートするように共に聖夜に祈りを捧げましょう🙏

参考

  1. コードハイライトでエラーになっているように見えますが、CSS Nesting Module に時代がまだ追いついていないだけで間違っているというわけではありません

  2. :where(): https://developer.mozilla.org/ja/docs/Web/CSS/:where

  3. :is(): https://developer.mozilla.org/ja/docs/Web/CSS/:is

21
2
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?