CSSクラス名の管理地獄から抜け出す|スケーラブルな命名戦略

CSSクラス名の管理地獄から抜け出す|スケーラブルな命名戦略
C
クリオ
Web制作ディレクター / フロントエンジニア

こんにちは!

今日は「CSSクラス名の管理地獄から抜け出す命名戦略」について、僕の失敗談を交えながら解説します。

クラス名で失敗した僕の実話

昔、僕がまだ駆け出しのエンジニアだった頃の話です。
小規模なWebサイトのリニューアルを担当していて、最初は「シンプルでいいや」って感じで.header.main.footerみたいなクラス名をつけていました。
ほんま、あの時は甘かった…。

プロジェクトが進むにつれて、ボタンが増えたり、カードコンポーネントが増えたりしていくわけです。
すると僕は.btn-red.btn-red-large.btn-red-large-hoverみたいな感じで、どんどんクラス名が増殖していったんです。
挙句の果てに.btn-red-large-hover-disabledなんて化石みたいなクラス名も生まれてしまいました。

3ヶ月後、デザインが少し変わって「赤いボタンを青にしよう」となった時、僕は絶望しました。
CSSファイルを開いたら、.btn-red関連のクラスが20個くらい散らばっていて、どれを変更すればいいのか分からなくなってしまったんです。
その時に悟りました:「クラス名の命名戦略、超大事やん」って。

クラス名がめっちゃ増えてしまう本当の理由

なぜクラス名は増殖し続けるのか。
それは、多くの人が「見た目」と「構造」を区別できていないからです。

例えば、こういう感じで命名してしまう人が多いんです:

  • .red-button(色で判定)
  • .large-text(サイズで判定)
  • .rounded-corner(形状で判定)

このアプローチの何が悪いかというと、デザイン変更に弱いということです。
赤が青に変わったら、クラス名まで変わるのか?という矛盾が生じます。
また、複数のスタイルを組み合わせるたびに新しいクラスを作る羽目になるので、クラス数が爆発的に増えてしまうわけです。

僕が見てきた現場では、このパターンで6,000行超えのCSSファイルを作ってしまった人もいます。
ほんま、メンテナンスの悪夢やん…。

命名戦略を決める3つのステップ

ステップ1:「何のためのクラスなのか」を明確にする

まず大事なのは、クラス名は「目的」を表すべき、ということです。
例えば:

  • .btn-primary(「主要なボタン」という役割)
  • .card-header(「カードの上部」という構造)
  • .is-active(「現在アクティブな状態」という状態)

こういう風に、クラス名がそのコンポーネントの「役割」や「意図」を伝えるようにするんです。
そうすることで、デザイン変更があっても、クラス名とCSS内容の関係性が保たれるわけです。

ステップ2:命名ルールを決めて、チーム全体で共有する

単語の区切り方は?
接頭辞や接尾辞の付け方は?
これらをルール化することが超大事です。

僕の現場でよく使われるパターンは、こんな感じです:

  • ケバブケース.button-primary.card-header(一番読みやすい)
  • ダブルハイフン表記.button__text.card__header(BEM形式の一種)
  • 接頭辞で状態を表現.is-active.has-error(状態管理が明確)

大事なのは、プロジェクト開始時に「うちはこのルールで行こう」と決めて、チーム全員が守ることです。
ルールなしに各自好きにやると、めっちゃカオスになります。

ステップ3:クラス名を「層」で分類する

これはめっちゃ実践的なテクニックなんですが、クラスを層ごとに分類することで、グッと管理しやすくなります:

  • 基本層.button.card(基本のコンポーネント)
  • バリエーション層.button-primary.card-large(色やサイズ)
  • 状態層.is-active.is-disabled(状態)
  • ユーティリティ層.text-center.margin-top-2(細かい調整)

こうすることで、「あ、このクラスはどの層に属するから、こうやって組み合わせるんだ」という整理がつくわけです。

プロジェクト別の命名パターン選択

ここまで「命名戦略の基本」を話してきましたが、実は最初に選ぶ「フレームワーク」によって、アプローチは変わります。

BEM形式で管理したい場合

.block__element--modifierという形式で、階層構造を明確にするやり方ですね。

例:

  • .card(ブロック)
  • .card__header(要素)
  • .card__header--featured(修飾子)

メリットは、関係性が超明確ということ。
デメリットは、クラス名が長くなることですね。
小〜中規模プロジェクトに向いています。

ユーティリティファーストで管理したい場合

TailwindCSSが有名ですが、.flex.justify-center.text-lgみたいに細かいユーティリティクラスを組み合わせるやり方です。

メリットは、CSS量が圧倒的に少ないこと。
デメリットは、HTMLが見辛くなることと、プロジェクト側でカスタムクラスの定義が増える可能性があること。
大規模でコンポーネント志向のプロジェクトに向いています。

CSS Modulesで管理したい場合

JavaScriptフレームワーク(React、Vue等)を使っている場合、CSS Modulesで自動的にクラス名をスコープ化するやり方があります。

例:import styles from './Button.module.css'