ウェブエンジニア問題集
第11章

詳細度とカスケード完全理解 — CSSが効かない原因の9割はここにある

10
この章の目次開く

「スタイルを書いたのに当たらない」「なぜか別のスタイルが優先される」——CSSでぶつかるトラブルの大半は、詳細度(Specificity)カスケードが原因です。逆に、この2つを理解すれば「CSSが効かない」問題はほとんど自力で解決できるようになります。

学習者学習者

スタイルを書いたのに効かない…!結局 !important を付けて無理やり通しちゃうんだけど、これでいいの?

!important は一時しのぎにはなりますが、後から更に困ることになります。まず「なぜ効かないのか」を理解する仕組みから見ていきましょう。

スタイルの優先順位に悩んでいるイメージ


カスケードとは — スタイルの優先順位を決めるルール

同じ要素に複数のスタイルが当たるとき、どれが勝つかを決める仕組みがカスケード(Cascade)です。CSSの「C」はまさにこれです。

優先順位は上から順に判定されます。

判定順ルール具体例
1. Origin!important > 作者のCSS > ブラウザのデフォルト!important が付いたスタイルは最優先
2. 詳細度より具体的なセレクタが勝つ#title.title に勝つ
3. 記述順同じ詳細度なら後に書いた方が勝つ同じ .btn の定義が2箇所あれば後者が適用

ほとんどの「効かない」トラブルは 2. 詳細度 が原因です。


詳細度の計算 — (A, B, C) の3桁

詳細度は (A, B, C) の3つの数値で表されます。左の桁ほど重みが大きく、左から順に比較して大きい方が勝ちます。

セレクタの種類加算される桁
インラインスタイル(style=""A に +1 → (1,0,0)<p style="color:red">
IDセレクタA に +1 → (1,0,0)#title
クラス・属性・擬似クラスB に +1.card, [type="text"], :hover
タイプ(要素)・擬似要素C に +1div, p, ::before
ユニバーサル(*)、結合子(>, +加算なし (0,0,0)*, .card > p>

計算例

p                     /* (0,0,1) — タイプ1つ */
.text                 /* (0,1,0) — クラス1つ */
p.text                /* (0,1,1) — タイプ1 + クラス1 */
#title                /* (1,0,0) — ID1つ */
.card p               /* (0,1,1) — クラス1 + タイプ1 */
.nav .item:hover      /* (0,3,0) — クラス2 + 擬似クラス1 */
#header .nav a        /* (1,1,1) — ID1 + クラス1 + タイプ1 */
div#content .text p   /* (1,1,2) — ID1 + クラス1 + タイプ2 */
css
学習者学習者

(0,3,0) って (0,1,2) より強いの?B桁が3 vs 1だから、C桁がいくつあっても勝てないってこと?

先生先生

そのとおり!左の桁が1でも大きければ、右の桁がどんなに積み上がっても逆転できない。クラス100個並べても、ID1つに勝てないんだ。


実際の競合を読み解く

クラス vs タイプセレクタの組み合わせ

nav a { color: red; }    /* (0,0,2) — タイプ2つ */
.link { color: blue; }   /* (0,1,0) — クラス1つ → こちらが勝つ */
css

タイプセレクタは C の桁に加算されるだけなので、クラス1つ(B に+1)に勝てません。

IDセレクタが強すぎる問題

#content { font-size: 14px; }  /* (1,0,0) */
.content { font-size: 16px; }  /* (0,1,0) — 負ける */
css

IDセレクタを使うと詳細度が跳ね上がり、クラスで上書きできなくなります。

同じ詳細度 → 後に書いた方が勝つ

.btn { background: blue; }   /* (0,1,0) */
.btn { background: green; }  /* (0,1,0) — 同じ詳細度 → 後者が勝つ */
css

CSSファイルの読み込み順や、<link> タグの順番でも同じ原理が働きます。複数のCSSファイルを読み込むとき、後に読んだファイルのスタイルが優先されます。


!important — 最終手段であり、ほぼ使うべきでない

p { color: red !important; }
p { color: blue; } /* これは負ける */
css

!important はOriginの段階で通常のスタイルに勝つため、詳細度を無視して強制適用されます。

!importantの連鎖で慌てるイメージ

問題は !important を上書きするには !important が必要なことです。

/* !importantの連鎖 — 絶対にやってはいけない */
.text { color: red !important; }
.text.highlight { color: blue !important; }    /* さらにimportant */
#main .text { color: green !important; }       /* さらにimportant + ID */
css
先生先生

!important を使いたくなったら、それは「詳細度の設計が壊れている」というサインだよ。セレクタを見直す方が正しい解決策なんだ。

!important が許容されるケース

  • サードパーティCSSの上書き:外部ライブラリのスタイルをどうしても変えたいとき
  • ユーティリティクラス:Tailwind CSSのような「最終的に勝つべきクラス」の定義

これ以外では基本的に使わないでください。


継承(Inheritance)

一部のプロパティは親要素から子要素に自動で引き継がれます。これを継承と呼びます。

body {
  font-family: sans-serif;
  color: #1a1a2e;
  line-height: 1.7;
}
/* ↑ すべての子孫要素にも適用される */
css

継承されるプロパティ・されないプロパティ

継承される継承されない
colormargin
font-family, font-sizepadding
line-heightborder
text-alignbackground
cursorwidth, height
visibilitydisplay

覚え方:テキストに関するプロパティは継承される、ボックスに関するプロパティは継承されない

継承を明示的に操作する

.child {
  border: inherit;   /* 通常継承されないborderを強制的に継承 */
  color: initial;    /* 継承を無視してブラウザのデフォルト値に戻す */
  all: unset;        /* すべてのプロパティを初期化 */
}
css

DevToolsでの詳細度確認

「なぜこのスタイルが当たらないのか」をDevToolsで確認する方法を知っておくと、デバッグが格段に速くなります。

  1. 要素を右クリック →「検証」でDevToolsを開く
  2. Styles パネルで、適用されているスタイルが上から優先順に表示される
  3. 打ち消し線が引かれているプロパティは、より詳細度の高いスタイルに負けている
  4. セレクタにカーソルを合わせると、詳細度 (A, B, C) が表示される(Chrome)

詳細度を低く保つ設計指針

プロジェクトが大きくなるほど、詳細度の管理が重要になります。

やるべきこと

  • クラスセレクタ中心で書く((0,1,0) 同士なら記述順で制御できる)
  • セレクタは短く保つ(.card-title > .card .content .title
  • BEM記法.block__element--modifier)でネストを浅くする

避けるべきこと

  • IDセレクタでスタイルを当てる
  • タイプセレクタの深いネスト(main section article p span
  • !important で無理やり通す
  • インラインスタイル(style="")を多用する
/* ❌ 詳細度が高すぎる */
#sidebar .nav ul li a.active { color: blue; }  /* (1,2,3) */
 
/* ⭕ クラス1つで十分 */
.nav-link--active { color: blue; }             /* (0,1,0) */
css

よくあるハマりどころ

リセットCSSとの競合

ブラウザのデフォルトスタイルを打ち消す「リセットCSS」は、タイプセレクタ (0,0,1) で書かれていることが多いです。クラスセレクタ (0,1,0) で書いていれば負けないので問題になりませんが、タイプセレクタ同士で書いていると記述順の勝負になり混乱します。

CSSファイルの読み込み順

<link rel="stylesheet" href="base.css">
<link rel="stylesheet" href="components.css">
<!-- components.css の方が後なので、同じ詳細度なら勝つ -->
html

読み込み順が意図と違うと、「書いたはずのスタイルが効かない」ことがあります。


ちゃんと使うためのポイント

  • セレクタはなるべく詳細度を低く保つ(クラス中心、IDや深いネストは避ける)
  • !important は使わない。使いたくなったらセレクタの設計を見直すサイン
  • 「スタイルが当たらない」ときはDevToolsのStylesパネルで打ち消し線と詳細度を確認する
  • テキスト系プロパティは継承される、ボックス系は継承されないと覚える
  • CSSファイルの読み込み順も優先順位に影響する

次の最終章では、実務で頻繁に使うCSSの実践パターン集をまとめます。

参考リンク

CSSクイズに挑戦するこの章で学んだCSSの知識を、4択クイズでアウトプットして定着させよう