CSSセレクタの優先順位は重要度、詳細度、記述順で判断する
公開日: 執筆:佐藤
同じ要素の同じプロパティへ複数のCSS宣言が適用されるときは、後に書かれた宣言が常に優先されるわけではありません。最初に!importantとスタイルシートの出所を比べ、条件が同じならセレクタの詳細度を比べます。記述順を使うのは、そこまで同じ場合です。
詳細度は、セレクタが要素をどれだけ限定しているかを、ID、クラスや属性、要素名の種類ごとに数えたものです。数字をすべて足さず、強い区分から順に比べます。
CSSの優先順位は三段階で決まる
CSS 2.1のカスケード仕様は、同じ要素とプロパティへ当てはまる宣言を、次の順で並べます。
- 宣言の重要度とスタイルシートの出所
- セレクタの詳細度
- 宣言が書かれた順序
詳細度だけを計算しても、!importantの有無や出所が違えば、優先順位は決まりません。反対に、重要度と出所が同じなら、詳細度が高いセレクタの宣言が優先されます。詳細度も同じ場合は、後に書かれた宣言が優先されます。
確認する対象は、CSSファイル全体ではありません。表示が合わない要素と、一つのプロパティを決め、その組み合わせに適用される宣言だけを比べます。colorの問題を調べるときに、同じ規則内のmarginまで優先順位へ含める必要はありません。
詳細度はstyle属性、ID、クラス、要素の列に分ける
CSS 2.1では、詳細度をa-b-c-dの四つに分けます。
| 区分 | 数えるもの | 例 |
|---|---|---|
| a | HTMLのstyle属性から指定された宣言 |
style="color: red" |
| b | IDセレクタ | #notice |
| c | クラスセレクタ、属性セレクタ、擬似クラス | .message、[title]、:hover |
| d | 要素名、擬似要素 | p、::first-line |
全称セレクタ*は、詳細度へ加えません。子孫を示す空白、子を示す>、隣接する兄弟を示す+などの結合子も、四つの区分には数えません。
四つの数字は、左から順に比べます。合計値にはしません。0-1-0-0のIDセレクタと0-0-2-0のクラス二つを比べると、最初に差が出るIDの列で前者が優先されます。
三つのセレクタを同じ要素で比べる
次のHTMLには、要素名、クラス、IDを一つずつ指定しています。これは詳細度の計算を示すための例であり、サトラボの実案件ではありません。
<p id="notice" class="message">受付時間を確認してください。</p>
同じcolorへ、三つの規則を指定します。
p {
color: black;
}
.message {
color: blue;
}
#notice {
color: red;
}
詳細度は次のようになります。
| セレクタ | a | b | c | d | 詳細度 |
|---|---|---|---|---|---|
p |
0 | 0 | 0 | 1 | 0-0-0-1 |
.message |
0 | 0 | 1 | 0 | 0-0-1-0 |
#notice |
0 | 1 | 0 | 0 | 0-1-0-0 |
三つの宣言は、重要度と出所が同じです。IDの列で差が付くため、#noticeのcolor: redが優先されます。.messageを後へ移しても、詳細度が低いままなら結果は変わりません。
同じ詳細度なら後に書かれた宣言が優先される
次の二つは、どちらもクラスセレクタ一つで、詳細度は0-0-1-0です。
.message {
color: blue;
}
.attention {
color: red;
}
同じ要素がclass="message attention"を持つ場合は、後に書かれた.attentionの宣言が優先されます。記述順が決め手になるのは、重要度、出所、詳細度が同じときです。
外部CSSファイルの読み込み順も、最終的な記述順へ影響します。上書き用の規則を別ファイルへ置く場合は、そのファイルが後から読み込まれていることだけでなく、競合するセレクタの詳細度も確認します。
!importantは詳細度を上げる記法ではない
!importantを付けた宣言は、通常の宣言より先に比較されます。これはセレクタのIDやクラスを増やして詳細度を上げる処理ではありません。
.message {
color: blue !important;
}
#notice {
color: red;
}
この二つが同じ作成者のスタイルシートにある場合、.messageの宣言が優先されます。通常宣言どうしなら#noticeの詳細度が高くても、重要度の比較が先だからです。
作成者の!important宣言どうしなら、その中で詳細度を比べます。CSS 2.1では、利用者が指定した!important宣言は、作成者の!important宣言よりも優先されます。利用者が必要な文字サイズや配色を指定できる余地を、作成者側の詳細度だけで判断してはいけません。
表示を直すたびに!importantを追加すると、次の修正でも重要宣言どうしを競わせることになります。先に競合する宣言を特定し、セレクタと読み込み順を直せるか判断します。
継承は詳細度の競争に参加しない
親要素へ指定したcolorが子要素へ伝わることと、子要素へ直接適用される宣言が競合することは別です。CSS 2.1の指定値に関する規則では、カスケードで値が決まればその値を使い、決まらない場合に、継承するプロパティなら親要素の算出値を使います。
親要素のIDセレクタが高い詳細度を持っていても、その詳細度を子要素が引き継ぐわけではありません。子要素へp { color: black; }が直接適用されるなら、親から継承する色ではなく、子要素の宣言が使われます。
表示が変わらないときは一つのプロパティから追う
CSSが上書きされないときは、対象の要素とプロパティを一つに固定します。次に、その組み合わせへ適用される宣言を集め、次の順で比べます。
- セレクタが対象要素に一致しているか
!importantの有無とスタイルシートの出所が同じかstyle属性、ID、クラス・属性・擬似クラス、要素・擬似要素の順で詳細度を比べたか- 詳細度まで同じなら、どちらが後に書かれているか
- 直接適用される宣言がない場合は、継承または初期値か
最初の一手は、表示を直したい要素について、変わらないプロパティを一つ選ぶことです。競合する宣言を二つ並べ、重要度、詳細度、記述順のどこで優先順位が決まったかを書き出してください。原因が分かれば、セレクタを必要以上に長くしたり、!importantを追加したりせずに修正できます。
関連記事

