特異性

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 を適用する必要がある場合があります。最も高い特異性を目指すと、その作業は難しくなります。

特異性は小数値ではなく、ABC の 3 つのコンポーネントで構成される三重子です。

  • A: ID のような特定度
  • B: クラスのような特定
  • C: 要素のような特定度

多くの場合、(A,B,C) 表記で表されます。(例: (1,0,2))。A-B-C という別の表記もよく使用されます。

特異性の 3 つのコンポーネント(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) です。セレクタの各部分は、セレクタのタイプに応じて AB、または 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 のような固有性を追加し、C コンポーネントを 1 増やします。

次の例では、特異性は (1,0,0) です。

#myID {
  color: red;
}

その他のセレクタ

CSS には多くのセレクタがあります。ただし、すべてが特定につながるわけではありません。たとえば、:not() 疑似クラス自体は、特定度の計算に何も追加しません。

ただし、引数として渡されたセレクタは、固有性の計算に追加されます。

div:not(.my-class) {
  color: red;
}

このサンプルの特定度は (0,1,1) です。これは、1 つのタイプ セレクタ(div)と :not()内部に 1 つのクラスがあるためです。

理解度を確認する

特異性スコアに関する知識をテストする

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,1) であるため、合計特異度は (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
要素は要素のような特定性(C コンポーネント)を追加します。セレクタに 2 つの要素があるため、このセレクタの特定度は (0,0,2) です。
article.card.dark
要素は要素のような特定度(C コンポーネント)を追加し、クラスはクラスのような特定度(B コンポーネント)を追加します。2 つのクラスと 1 つの要素があるため、このセレクタの特異性は (0,2,1) になります。
article:hover a[href]
要素は要素のような固有性(C コンポーネント)を追加し、疑似クラスと属性はクラスのような固有性(B コンポーネント)を追加します。要素セレクタが 2 つ(2 × (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;
}

これは、両方のセレクタの特異性が同じであるためです。この場合、カスケードは表示順序のステップにフォールバックします。

リソース