TL;DR
同じ要素に対して競合する CSS の宣言があるとき、どれを適用するかを決めるためのセレクタの重み。英語では Specificity という。
仕組み
ブラウザはまずオリジンと重要度(!important)でカスケードを決め、同じ条件の中で競合した宣言を詳細度で比べる。
詳細度は ID、CLASS、TYPE の 3 つの列で数える。
| 列 | 数えるもの | 例 | 重み |
|---|---|---|---|
| ID | ID セレクタ | #main | 1-0-0 |
| CLASS | クラス、属性セレクタ、擬似クラス | .btn、[type="text"]、:hover | 0-1-0 |
| TYPE | 要素型セレクタ、擬似要素 | p、::before | 0-0-1 |
左の列から順に比べ、最初に差が出た列で優先順位が決まる。TYPE の列がいくつあっても、CLASS の列 1 つには勝てない。詳細度がすべて同じなら、後に書いた宣言が優先される。全称セレクタ * と結合子(>、+、~、空白)は詳細度に影響しない。
例
#myElement {
color: green;
} /* 1-0-0。こちらが適用される */
.a .b .c .d [id="x"] {
color: yellow;
} /* 0-5-0 */:is()、:not()、:has() は、それ自体は重みを持たず、引数の中で最も詳細度の高いセレクタの重みが加わる。:where() は引数にかかわらず常に 0-0-0 になる。
注意点
インラインスタイル(style="...")は、どのセレクタよりも優先される。!important は詳細度とは別の仕組みで、同じオリジンとレイヤーの中では通常の宣言より優先される。MDN は !important を悪い習慣としており、使うなら理由をコメントに残すよう勧めている。詳細度に頼らずに優先順位を制御するには、カスケードレイヤー(@layer)を使う。