本文へスキップ
スキルアップカレッジ

なぜ CSS は壊れるのか——詳細度とカスケードを整理する

レッスン1:なぜ CSS は壊れるのか——詳細度とカスケードを整理する

このレッスンで学ぶこと

  • 本コースが扱う範囲と、扱わない範囲を理解する
  • CSS が壊れていく典型的な経過を知る
  • 詳細度の数え方を理解する
  • カスケードによる適用順の決まり方を理解する
  • !important に頼ることの副作用を理解する
  • 本コースを貫く 6 個の中核メッセージを知る

本コースは、HTML と CSS の基礎(セレクタ・ボックスモデル・Flexbox)を学び終えた方に向けた続編です。セレクタの種類やボックスモデル、display: flex を使った横並びのレイアウトはすでに書けることを前提に進めます。もしこのあたりの記憶があいまいであれば、Web 制作関連の入門コースで基礎を確認してから戻ってきてください。

ここから先で扱うのは、「正しく書けるようになったあと」の課題です。1 つのページなら問題なく書けるのに、ページが増え、機能が増え、関わる人が増えると、なぜか CSS が思いどおりに効かなくなっていく——多くの人が一度は経験するその現象を、順番に整理していきます。

本コースの立ち位置

最初に、本コースが何を扱い、何を扱わないかをはっきりさせておきます。

本コースが全面的に扱うのは、CSS の設計・命名・変数・Grid・部品化です。詳細度とカスケードの整理、役割にもとづく命名規則、CSS カスタムプロパティによる値の一元管理、CSS Grid を使った 2 次元のレイアウト、コンポーネントとしての設計、ユーティリティファーストという選択肢、そして小さなデザインシステムの構築までが守備範囲です。

一方で、扱わない領域もあります。

  • 型システムや JavaScript の言語仕様:TypeScript 関連の入門コースに譲ります
  • 業務の自動化や市民開発:ノーコード関連の入門コースに譲ります
  • 画面幅に応じたレイアウトの切り替えそのもの:Flexbox の基本操作やメディアクエリ、ブレークポイントの決め方は、Web 制作関連の入門コースがすでに扱っています。本コースはこれを前提知識として扱い、あらためて教え直すことはしません
  • 色だけに頼らないなど、達成基準にもとづくアクセシビリティの検証:UX 関連の入門コースに譲ります

つまり本コースは、「正しく書く」段階を終えた人が、「増えても壊れない書き方」に進むための続編です。

🔰 初学者の方へ 「レスポンシブ対応の書き方をもう一度確認したい」という場合は、本コースの前に Web 制作関連の入門コースへ戻ることをおすすめします。本コースでは、画面幅への対応方法そのものは扱いません。

CSS が壊れていく典型的な経過

CSS が壊れるとき、多くの場合は一気に壊れるのではなく、段階を踏んで壊れていきます。典型的な経過を 3 段階で見てみましょう。

第 1 段階:小さく、きれいに始まる

最初は数個のクラスで足ります。ページも少なく、書いた本人がすべてを把握できています。

.card {
  padding: 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

このくらいの規模なら、どこに何が効いているかで迷うことはまずありません。

第 2 段階:例外にパッチを当てる

ページが増え、「このページだけ少し違う見た目にしたい」という要望が出てきます。ここで、既存のクラスに例外を上書きするセレクタが追加されがちです。

.sidebar .card {
  padding: 12px;
}

#promo-section .card.featured {
  padding: 24px;
  border-color: #f39c12;
}

1 つ 1 つは小さな変更です。ですが、.card に対する指定が複数の場所に分散し、「結局どの padding が効くのか」を追うコストが少しずつ増えていきます。

第 3 段階:誰も触れなくなる

パッチが積み重なると、ある要素の見た目を変えたいときに、影響範囲が予測できなくなります。「ここを直したら、別のページのカードが崩れた」という事故が起き始め、次第に「触らないほうが安全」という空気が生まれます。

⚠️ 注意 ここまでの 3 段階に、書き手の技量はほとんど関係ありません。1 つ 1 つの指定は、単体で見れば正しい CSS です。問題は、指定が増えるほど「どこに何が効いているか」を追うコストが増えていくという、CSS の構造そのものにあります。

中核メッセージ 1:CSS が壊れるのは、どこに何が効いているかを追えなくなったときです。書き方が下手だからではありません。

カスケードとは何か

CSS は「Cascading Style Sheets」の略で、日本語では「連なって落ちるスタイルシート」という意味です。この「カスケード」こそが、複数のルールが同じ要素にぶつかったときに、どのルールを適用するかを決める仕組みです。

カスケードは、大まかに次の順番で優先順位を決めます。

  1. !important が付いているかどうか
  2. 詳細度(どれだけ限定的なセレクタか)
  3. ソース順(あとに書かれたルールが勝つ)

つまり、同じ要素に複数のルールが競合したとき、ブラウザは機械的にこの順番で「どれを採用するか」を判定しています。感覚や偶然ではなく、明確な規則があります。

p {
  color: navy;
}

p {
  color: green;
}

この 2 つのルールは詳細度が同じなので、あとに書かれた color: green が適用されます。これがもっとも単純なカスケードの例です。

詳細度の数え方

詳細度は、セレクタがどれだけ限定的かを表す指標です。MDN Web Docs では、セレクタを 3 つの区分に分け、それぞれの区分に含まれる個数を「ID・クラス・タイプ」の 3 列で数える方法が示されています。

  • ID の列:ID セレクタ(#header など)の個数
  • クラスの列:クラスセレクタ・属性セレクタ・疑似クラス(.card、[type="text"]、:hover など)の個数
  • タイプの列:要素セレクタ・疑似要素(p、div、::before など)の個数

比較は列ごとに、左から右へ行われます。ID の列が多いセレクタが、ほかの列の数に関わらず勝ちます。

#promo .card {
  /* ID 1 個、クラス 1 個 → 1-1-0 */
  color: orange;
}

.sidebar .card.featured {
  /* ID 0 個、クラス 3 個 → 0-3-0 */
  color: navy;
}

クラスの数で見れば下のセレクタのほうが多く見えますが、ID の列で上のセレクタが勝っているため、color: orange が適用されます。ID セレクタは 1 個でも、クラスをいくつ重ねた指定より強くなります。

* {
  /* 全称セレクタは詳細度に加算されない → 0-0-0 */
  margin: 0;
}

button {
  /* 要素セレクタ 1 個 → 0-0-1 */
  padding: 8px;
}

全称セレクタ(*)はどの要素にも一致しますが、詳細度には数えられません。もっとも弱いセレクタです。

💡 ポイント 詳細度は「セレクタの長さ」ではなく「セレクタの種類」で決まります。.a .b .c .d のようにクラスを 4 個連ねても、ID セレクタ 1 個には勝てません。文字数の多さと詳細度の強さは別物です。

ソース順――同じ強さなら後着が勝つ

詳細度がまったく同じ場合は、ファイルの中であとに書かれたルールが採用されます。これがソース順です。

.button {
  background: #2c3e50;
}

/* 別の場所、あとに書かれたルール */
.button {
  background: #e74c3c;
}

両方とも詳細度は同じ(クラス 1 個)なので、ファイルの下側にある background: #e74c3c が勝ちます。読み込む CSS ファイルが複数ある場合は、あとから読み込まれたファイルのほうが有利になります。

ここまでをまとめると、カスケードは「強さ(!important)→ 詳細度 → 順番」という明確な階層で決着します。CSS が予測不能に見えるとき、実際はこの 3 つのどれかで説明が付くことがほとんどです。

flowchart TD
  A[同じ要素に複数のルールが競合] --> B{importantが付いているか}
  B -->|付いている方が勝つ| Z[適用ルールが決まる]
  B -->|どちらも付いていない| C{詳細度に差があるか}
  C -->|高いほうが勝つ| Z
  C -->|同じ詳細度| D[あとに書かれたルールが勝つ]
  D --> Z

この図は、ブラウザが競合するルールをどの順番で判定しているかを表しています。上から下へ、条件に当てはまった時点で決着が付きます。

!important に頼るとどうなるか

思ったスタイルが反映されないとき、!important を付けると強制的に優先させることができます。

.card {
  padding: 12px !important;
}

!important は、カスケードの階層の中でもっとも強い扱いを受けます。詳細度やソース順を無視して勝ちます。ただし、これは「効く」のであって「解決した」わけではありません。

!important には落とし穴があります。あとから別の場所で同じプロパティを上書きしたくなったとき、通常の指定では歯が立たなくなります。上書きするには、さらに強い !important を書くしかありません。

/* 元の指定 */
.card {
  padding: 12px !important;
}

/* あとから別のページで上書きしたい */
.promo .card {
  padding: 24px !important; /* これでようやく効く */
}

一度この対応をすると、次に上書きしたい場面でもまた !important が必要になります。強さで解決した問題は、次はもっと強い指定を要求してきます。

中核メッセージ 2:強さで勝とうとすると、次はもっと強く書くことになります。!important の連鎖は、一度始まると降りるのが難しい競争です。

⚠️ 注意 !important そのものが絶対悪というわけではありません。ユーティリティクラスなど、意図的に「常に勝たせたい」指定にかぎって使う設計もあります(レッスン6 で扱います)。問題なのは、詳細度の整理を諦めた結果として無計画に使われることです。

強さで勝とうとしない、という原則

ここまで見てきたように、CSS が壊れていく多くのケースは、「上書きされたら、より強い指定で対抗する」という発想の積み重ねから生まれます。ID セレクタを使い、詳細度の高いセレクタを連ね、最後は !important を重ねる。この道筋を進むほど、あとから来る人はさらに強い指定を書くしかなくなります。

この連鎖を断ち切る方法は、実は単純です。最初から詳細度を低く、均一に保つことです。クラスセレクタだけで指定を組み立て、ID セレクタや深いネストを避ければ、どのルールも同じ強さで競合するため、ソース順という予測しやすい基準だけで決着が付きます。

この考え方は、次のレッスン以降で扱う命名規則やコンポーネント設計の土台になります。「強さで勝つ」のではなく「衝突しない名前を付ける」ほうへと、発想を転換していきます。

本コースを貫く 6 個の中核メッセージ

このレッスンの最後に、本コース全体を通して繰り返し立ち返る 6 個のメッセージを並べておきます。各レッスンの中で、あらためて登場します。

  1. CSS が壊れるのは、どこに何が効いているかを追えなくなったときである
  2. 強さで勝とうとすると、次はもっと強く書くことになる
  3. 名前は見た目ではなく役割で付ける
  4. 同じ値を何度も書いた時点で、それは変数にすべきものである
  5. 部品は、置かれる場所を知らないほど再利用できる
  6. 守られないルールは、ルールが厳しすぎるからである

📝 補足 6 個のうち、1 と 2 は本レッスンで扱いました。3 はレッスン2、4 はレッスン3、5 はレッスン5、6 はレッスン7 で中心的に扱います。ほかのレッスンでも、関連する場面で繰り返し触れます。

実習:詳細度を予想してから答え合わせをする

次の CSS を読んで、<p class="lead"> に最終的に適用される文字色を予想してから、実際にブラウザで確認してみましょう。HTML と CSS をエディタに用意し、.lead を持つ段落を 1 つ作って試してください。

p {
  color: #333;
}

.lead {
  color: #2c3e50;
}

article p.lead {
  color: #16a085;
}

#main .lead {
  color: #8e44ad;
}

予想の手順は次のとおりです。

  1. それぞれのセレクタの詳細度を「ID・クラス・タイプ」の 3 列で書き出す
  2. もっとも詳細度が高い行を探す
  3. 同じ詳細度の行があれば、あとに書かれたほうを選ぶ
  4. 予想した色を、実際にブラウザの開発者ツールで確認する

開発者ツールの「要素を検証」を開くと、競合するルールが取り消し線付きで一覧表示され、どのルールが実際に採用されたかを確認できます。詳細度の理解を検証する近道になります。

まとめ

このレッスンでは、以下のことを学びました。

  • 本コースは、CSS の設計・命名・変数・Grid・部品化を扱う続編であり、画面幅への対応や型システムなどはほかの入門コースに譲ること
  • CSS は小さく始まり、例外へのパッチが積み重なることで、誰も触れない状態へと壊れていくこと
  • カスケードは「!important → 詳細度 → ソース順」の順で優先順位を決めること
  • 詳細度は「ID・クラス・タイプ」の 3 列で数えられ、列ごとに左から比較されること
  • !important は強力ですが、上書きのたびにさらに強い指定を要求する連鎖を生むこと
  • 強さで勝とうとせず、詳細度を低く均一に保つことが、壊れない CSS への第一歩であること

次のレッスンでは、CSS が壊れるもう 1 つの大きな原因である「名前の付け方」を扱います。見た目に由来する名前がなぜ破綻するのか、役割で名付けるとはどういうことかを、BEM の考え方とともに整理していきます。


確認クイズ

このレッスンの理解度をチェックしましょう。