「CSSが効かない!」を解決。スタイルの優先順位と詳細度のルール
CSSを学び始めると、誰もが一度は「なぜこのCSSが効かないんだ?」という壁にぶつかります。スタイルを適用したはずなのに、見た目が変わらない…。
この現象のほとんどは、CSSが持つ明確な「スタイルの競合を解決するためのルール」を知らないことが原因です。CSSには、複数のスタイルが同じ要素に適用されようとした場合に、どのスタイルを優先するかが厳密に定められています。このルールを理解すれば、CSSのデバッグ(問題解決)は格段に楽になります!
1. カスケード (Cascade) :スタイルの流れ
CSSの「C」は「Cascading(カスケード)」を意味します。これは、スタイルが滝(cascade)のように上から下へと流れ、複数のスタイルシートが合流して最終的なスタイルが決定される様子を表しています。
基本的な優先順位は以下の通りです。
通常、あなたが作成したCSSがブラウザのデフォルトよりも優先されます。問題は、**あなたのCSSファイル「内部」でスタイルが競合した場合**です。その解決に使われるのが、次の「詳細度」です。
2. 詳細度 (Specificity) :セレクタの強さを決めるルール
ブラウザは、同じ要素に対して複数のCSSルールが競合した場合、「どちらのセレクタがより具体的(= 強い)か」を判断します。この「具体性」を数値化したスコアが「詳細度」です。
セレクタの強さランキング
詳細度は、セレクタの種類に基づいて計算されます。簡易的ですが、以下の「強さの階層」で覚えるのが一番分かりやすいです。
| 強さ (強→弱) | 種類 | 例 | スコア (簡易) |
|---|---|---|---|
| 1位 (最強) | インラインスタイル | style="..." |
1-0-0-0 |
| 2位 | IDセレクタ | #id |
0-1-0-0 |
| 3位 | クラス・属性・擬似クラス | .class, [type="text"], :hover |
0-0-1-0 |
| 4位 (最弱) | 要素セレクタ・擬似要素 | p, ::before |
0-0-0-1 |
スコア計算の重要ルール
このスコアは、単純な足し算ではありません。「ID, クラス, 要素」の各列で比較されます。最も重要なルールは、「IDが1つでもあれば、クラスが100個あってもIDが勝つ」ということです。
例えば、以下のHTMLとCSSがあった場合、テキストは何色になるでしょうか?
HTML:
<div id="content">
<p class="text">このテキストの色は?</p>
</div>
CSS:
/* セレクタA */
#content p {
color: blue;
}
/* セレクタB */
div p.text {
color: red;
}
答えは「青色」です。
それぞれの詳細度スコアを見てみましょう。
- セレクタA (
#content p):- ID (
#content) x 1 - 要素 (
p) x 1 - スコア: 0-1-0-1
- ID (
- セレクタB (
div p.text):- クラス (
.text) x 1 - 要素 (
div,p) x 2 - スコア: 0-0-1-2
- クラス (
セレクタBはクラス1つ、要素2つで合計3つですが、セレクタAはIDを1つ含んでいます。「IDの列」で 1 対 0 となり、その時点でセレクタA(青色)の勝ちが決定します。
3. ソース順 (Source Order) :最終的な決定打
もし、二つのセレクタの「詳細度」が全く同じスコアだった場合、単純なルールが適用されます。
「最後に記述されたルール(CSSファイルの下にあるルール)が勝つ」
/* 同じ詳細度 (0-0-1-1) */
p.info { color: green; }
/* こちらが適用される! */
p.info { color: orange; }
この場合、テキストはオレンジ色になります。
4. 例外:最終兵器「!important」
!important というキーワードを宣言の最後に追加すると、そのスタイルは詳細度やソース順を含む全てのルールを無視して最優先で適用されます。
p {
color: purple !important; /* !important付き */
}
#main p {
color: black; /* こちらのほうが詳細度は高いが… */
}
この場合、IDセレクタ(黒色)の方が詳細度が高いにもかかわらず、!important が付いているため、段落の文字は紫色になります。