The CSS Podcast - 003: Specificity
次の HTML と CSS を使用しているとします。
<button class="branding">Hello, Specificity!</button>
.branding {
color: blue;
}
button {
color: red;
}
ここでは、同じ要素をターゲットとするルールが 2 つあります。各ルールには、ボタンの色を設定する宣言が含まれています。1 つはボタンを赤くしようとし、もう 1 つは青くしようとします。要素に適用される宣言はどれですか。
CSS の詳細度アルゴリズムを理解することは、競合する宣言の間で CSS がどのように判断するかを理解するうえで重要です。
特定性は、カスケードの明確なステージの 1 つです。これは、前回のモジュールのカスケードで説明しました。
特異性スコア
オリジン内の各セレクタルールにスコアが付けられます。特定度は合計スコアと考えることができ、各セレクタタイプはそのスコアに対してポイントを獲得します。最も特定度の高いルールの宣言が優先されます。
実際のプロジェクトでは、適用する予定の CSS ルールが実際に適用されるようにしながら、複雑さを防ぐためにスコアを低く保つというバランスを取る必要があります。特異度は、可能な限り高い特異度を目指すのではなく、必要なだけ高くする必要があります。今後、より重要な CSS を適用する必要がある場合があります。最も高い特異性を目指すと、その作業は難しくなります。
特異性は小数ではなく、A、B、C の 3 つのコンポーネントで構成される三重子です。
A: ID のような特定度B: クラスのような特定C: 要素のような特定度
多くの場合、(A,B,C) 表記で表されます。(例: (1,0,2))。A-B-C という別の表記もよく使用されます。
特異性を比較する方法
特異性は、3 つのコンポーネントを順番に比較して比較されます。A 値が大きい特異性がより特異性が高いです。2 つの A 値が同等の場合は、B 値が大きい特異性がより特異性が高いです。2 つの B 値も同等の場合は、C 値が大きい特異性がより特異性が高いです。すべての値が同等の場合は、2 つの特異性は等しくなります。
たとえば、(1,0,0) の A 値(1)は (0,4,3) の A 値(0)よりも大きいため、(1,0,0) は (0,4,3) よりも特異性が高いと見なされます。
セレクタは特定性に影響する
特定性の 3 つの部分はそれぞれ 0 の値で始まるため、デフォルトの特定性は (0,0,0) です。セレクタの各部分は、セレクタのタイプに応じて A、B、または C の値を増分する特定性を高めます。
ユニバーサル セレクタ
ユニバーサル セレクタ(*)は特定度を追加しません。値は初期の特定度 (0,0,0) のままになります。
* {
color: red;
}
要素または疑似要素のセレクタ
要素(タイプ)または疑似要素セレクタは、要素のような固有性を追加し、C コンポーネントを 1 増やします。
次の例では、全体的な特定度は (0,0,1) です。
タイプセレクタ
div {
color: red;
}
疑似要素セレクタ
::selection {
color: red;
}
クラスセレクタ、疑似クラスセレクタ、属性セレクタ
クラス、疑似クラス、属性セレクタは、クラスのような固有性を追加し、B コンポーネントを 1 増やします。
次の例の特定度は (0,1,0) です。
クラスセレクタ
.my-class {
color: red;
}
擬似クラス セレクタ
:hover {
color: red;
}
属性セレクタ
[href='#'] {
color: red;
}
ID セレクタ
ID セレクタは、属性セレクタ([id="myID"])ではなく ID セレクタ(#myID)を使用する限り、ID のような固有性を追加し、A コンポーネントを 1 増やします。
次の例では、特異性は (1,0,0) です。
#myID {
color: red;
}
その他のセレクタ
CSS には多くのセレクタがあります。ただし、すべてが特定性を高めるわけではありません。たとえば、:not() 疑似クラス自体は、特定度の計算に何も追加しません。
ただし、引数として渡されたセレクタは、固有性の計算に追加されます。
div:not(.my-class) {
color: red;
}
また、[:is()](https://developer.mozilla.org/en-US/docs/Web/CSS/:is) 疑似クラス自体は、固有性の計算に追加されません。:not() と同様に、最も具体的な引数の特定度を取得します。
:is(h1, h2, h3) {
color: blue;
}
このサンプルは、セレクタの種類が 1 つ(type)しかないため、特異性が (0,0,1) です。
id を追加すると、特異性が (1,0,0) に増加します。
:is(h1, h2, h3, #my-heading) {
color: blue;
}
[:where()](https://developer.mozilla.org/docs/Web/CSS/:where) 疑似クラスは異なります。引数の特定度に関係なく、常に (0,0,0) の特定度になります。
:where(h1, h2, h3, #my-heading) {
color: blue;
}
:where() を使用して適用される低い特定度のスタイルは、スタイルシートの後半で基本セレクタを使用してオーバーライドできます。
:where(#my-content) {
color: red;
}
p {
color: blue;
}
:where() の引数リストに id が含まれていても、その固有性は (0, 0, 0) に過ぎないため、基本的な p セレクタによってオーバーライドされ、テキストは blue になります。
理解度を確認する
特異性スコアに関する知識をテストする
a[href="#"] の特定度
(0,0,1)a の値は (0,0,1) ですが、[href="#"] の値は (0,1,0) です。(0,1,0)a の値は (0,0,1) ですが、[href="#"] の値は (0,1,0) です。(0,1,1)a の値は (0,0,1)、[href="#"] の値は (0,1,0) であるため、総特異度は (0,1,1) となります。特異性に影響しない要因
特異性に影響する次の要素について、よくある誤解をご紹介します。
インラインのスタイル属性
要素の style 属性に直接適用された CSS は、カスケードの別のステップで、特定度より前に評価されるため、特定度には影響しません。
<div style="color: red"></div>
スタイルシート内からこの宣言をオーバーライドするには、カスケードの前のステップで宣言の優先度を高める必要があります。
たとえば、!important を追加して、作成された !important オリジンの一部にすることができます。
!important 件の申告
CSS 宣言の末尾にある !important は特定性に影響しませんが、宣言を別のオリジン(作成者 !important)に配置します。
次の例では、.my-class の特定性は、!important 宣言が優先されるかどうかに関係ありません。
.my-class {
color: red !important;
color: white;
}
2 つの宣言が !important の場合、カスケードの起点ステップで勝者をまだ決定できなかったため、再び特定性が考慮されます。
.branding {
color: blue !important;
}
button {
color: red !important;
}
コンテキスト内の特異性
複雑なセレクタまたは複合セレクタを使用する場合、そのセレクタの各部分が特定性に加算されます。次の HTML の例について考えてみましょう。
<a class="my-class another-class" href="#">A link</a>
このリンクには 2 つのクラスがあります。次の CSS のルールの限定性は (0,0,1) です。
a {
color: red;
}
セレクタでいずれかのクラスを参照すると、(0,1,1) の特殊性が付与されます。
a.my-class {
color: green;
}
他のクラスをセレクタに追加すると、特定度が (0,2,1) になります。
a.my-class.another-class {
color: rebeccapurple;
}
セレクタに href 属性を追加すると、(0,3,1) の特定性が設定されます。
a.my-class.another-class[href] {
color: goldenrod;
}
最後に、:hover 疑似クラスをすべてに追加すると、セレクタの特殊性は (0,4,1) になります。
a.my-class.another-class[href]:hover {
color: lightgrey;
}
理解度を確認する
特異性スコアに関する知識をテストする
次のセレクタのうち、特異性が (0,2,1) なのはどれですか。
article > section(0,0,2) です。article.card.dark(0,2,1) になります。article:hover a[href](0,0,1))、属性セレクタが 1 つ((0,0,1))、クラスセレクタが 1 つ((0,0,1))あるため、このセレクタの合計固有度は (0,2,2) となります。実用的に特定度を高める
次のような CSS があるとします。
.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
HTML は次のようになります。
<button class="my-button" onclick="alert('hello')">Click me</button>
2 番目のセレクタの固有性 (0,1,1) が原因で、ボタンの背景がグレーになっています。これは、1 つのタイプ セレクタ(button)((0,0,1))と 1 つの属性セレクタ([onclick])((0,1,0))があるためです。
前のルール .my-button は、クラスセレクタが 1 つあり、(0,1,1) よりも特定性が低いため、(0,1,0) と同じです。
このルールを優先する場合は、次のようにクラス セレクタを繰り返します。
.my-button.my-button {
background: blue;
}
button[onclick] {
background: grey;
}
新しいセレクタに特定度 (0,2,0) が設定されるため、ボタンの背景が青色になります。
特定度が同じ場合は、カスケードの次のステップにフォールバックします。
ボタンの例を引き続き使用し、CSS を次のように変更します。
.my-button {
background: blue;
}
[onclick] {
background: grey;
}
ボタンの背景はグレーです。これは、両方のセレクタの特異性が (0,1,0) で同じためです。
ソースの順序でルールを切り替えると、ボタンは青色になります。
[onclick] {
background: grey;
}
.my-button {
background: blue;
}
これは、両方のセレクタの特異性が同じであるためです。この場合、カスケードは表示順序のステップにフォールバックします。