PR

CSSで安易なネストは使うな【Sassもだよ】

HTML/CSSを学ぶ

こんにちは。Chrome112でCSSのネストが使えるようになりました。

Chrome 112: CSS のネスト、animation-composition、FormData コンストラクタの submitter パラメータ
Chrome 112: CSS のネスト、animation-composition、FormData コンストラクタの submitter パラメータ

Can I Useを見るとまだモダンブラウザはほとんど対応していません(2023/04/05現在)が、基本的には後追いで実装する流れになるでしょう。

CSS Nesting | Can I use... Support tables for HTML5, CSS3, etc
"Can I use" provides up-to-date browser support tables for support of front-end web technologies on desktop and mobile w...

Twitterの反応を見ても概ね歓迎されています。

しかし、僕は正直ネストの利用はかなり反対派で、よほど明確な理由がない時以外は禁止にしても良いと思っています。

その理由を書いていきます。ざっくり言うと管理不可能になってカオスになるからです。

ネストが深かったり記述量が多かったりすると親子関係が見えなくなる

人間がコードを書く以上、人間が一目で見えるかどうかの制約があります。

例えば.Sectionクラスにいろいろネストした場合を見てみましょう。

ネストされた要素を見るためにスクロールしていくと、親の.Sectionが見えなくなります。コードが多ければ多いほど今見ているクラスが何の子要素なのか把握しにくくなり、コーディングの質の低下の原因になります。

ネストが深い場合も、親子関係が見にくかったり単純に見づらいなど問題が多いです。

このように可読性が下がり、ひいては保守性の定価につながります。特に複数人で開発している場合はこのようなコードを初見で対応するケースが発生して本当に大変です。

詳細度が複雑になる

これはネスト特有の問題ではありませんが、ネストを使う以上確実に発生する問題です。

詳細度とは、ある要素に対して複数のセレクタでCSSが定義されているとき、どれを最終的に使用するかを決める概念です。

詳細度 - CSS: カスケーディングスタイルシート | MDN
詳細度 (Specificity) は、ある要素に最も関連性の高い CSS 宣言を決定するためにブラウザーが使用するアルゴリズムで、これによって、その要素に使用するプロパティ値が決定されます。詳細度のアルゴリズムは、CSS セレクターの重み...

例えば次のコードがあるとします。

<main class="Main">
  <section class="Section">
    <div class="Content" id="Content"></div>
  </section>
</main>
#Content {
  width: 100%;
  height: 300px;
  background-color: blue;
}

.Content {
  width: 100%;
  height: 300px;
  background-color: red;
}

.Section {
  .Content {
    width: 100%;
    height: 300px;
    background-color: green;
  }
}

.Main 
  .Content {
    width: 100%;
    height: 300px;
    background-color: purple;
  }

  .Section {
    .Content {
      width: 100%;
      height: 300px;
      background-color: pink;
    }
  }
}

さて、どれが実際に適用されるか分かりますか?・・・

















パッと見てすぐに答えを出すのは難しいですよね。

正解は#Content、idセレクタです。ちなみにネストは子孫セレクタ扱いのようです。

もちろん計算方法を知っていれば導けますが、毎回これを考えなければならないのは大変です。さらに兄弟セレクタや親子セレクタなどが入ってきたらもっと複雑になります。

同じクラス名が乱立し、可読性が下がる

ネストをしたい目的は、特定の範囲にのみ有効になるいわゆるスコープ付きCSSにしたいというのがあります。

次のHTMLがあったとき、.Section内のContentにだけCSSを適用したいときに使うということです。

<main class="Main">
  <section class="Section">
    <div class="Content"></div>
  </section>

  <div class="Content"></div>
</main>
.Section {
  .Content {
    width: 100%;
    height: 300px;
    background-color: green;
  }
}

このCSSは.Section内の.Contentにのみ影響します。一見良さそうですが、同じクラス名なのに片方にはあるCSSが適用されて片方には適用されない、もしくは別のCSSが適用されているという奇妙な状態を引き起こします。

少なくともHTMLからはどんなCSSが適用されているかが全く予想できなくなります。これは本当に最悪で、同じ名前を付けている意味が全くなくなります。

ReactやVue、Astroなどのコンポーネント機能を持つライブラリを使っている場合はそのコンポーネント内で整理されていれば良いですが、通常のHTML/CSSは基本的に全て並列に要素、スタイルが書かれますので上記のコードは混乱しか生みません。

文字列検索しにくくなる

これまでの問題に関連するのですが、人間が読みにくいのであればツールや仕組みに頼ることになります。真っ先に考えられるのは全文検索ですが、これが機能しにくくなります。

次にようなコードを考えます。

<main class="Main">
  <section class="Section">
    <div class="Content"></div>
  </section>

  <div class="Content"></div>
</main>
.Section {
  .Content {
    width: 100%;
    height: 300px;
    background-color: green;
  }
}

.Content {
  width: 100%;
  height: 300px;
  background-color: red;
}

「.Content」を文字列検索すると、上記2つのセレクタがヒットします。これは検索した意味があまりありません。結局それぞれの親子関係などを確認して目的のCSSがどれかを探さなければなりません。

またSassの話で言えば&で文字を繋ぐ書き方がありますが、これは本当に最悪でそもそも検索に引っかかりません。

.Foo {
  &__Bar { // これが.Foo__Barで検索しても引っかからない
    // etc
  }
}

検索して見つからないならもうお手上げです。数千行から数万行に及ぶCSSから手動で目的のCSSをすぐに探せますか?

まとめ

というわけで安易にネストを使うとこんなに大変になるという話でした。

こういう細かい話は割と無視されやすく、「自分が書きやすい」「なんとなく楽」という点が優先されがちです。しかしそれでは、はっきり言って余計なことをするダメなエンジニアです。

そういう細かいテクニックをもっと知ってレベルアップしたい方はぜひこちらの本で勉強してみてください。

【脱・初心者】教材だけでは分からない、案件でよく要求される細かいコーディングのテクニック30選 + α - セカヤサBooks
フリーランスのフロントエンドエンジニアとして7年間、サイト制作やWebアプリケーション開発の案件に携わってきた中で「これは伝えたい」と思ったコーディングのテクニックをまとめました! 正直言うと、これができているかどうかが「プロかプロでないか...

コメント

タイトルとURLをコピーしました