CSSの特異性とは、ブラウザーがCSSスタイルの重要性、関連性、および「優先度」をどのように決定するかを指します。 ここでは、すべてのCSSスタイリングタイプを確認し、会社の例えを使用して、競合するスタイルがどのように解決されるかを理解します。

CSSセレクターの概要

CSSでスタイルを設定しようとしている要素を選択する方法は複数あります。 すべてのオプションを確認することから始めましょう。

  • タイプセレクター:要素タイプを使用して目的の要素を選択します。 たとえば、すべての<p>タグを選択するには、CSSスタイルシートでpを使用します。
  • 疑似要素:名前が示すように、疑似要素はそれ自体が要素ではありませんが、別のセレクターに関連するHTMLの一部を選択できます。 たとえば、p::first-letterで各段落の最初の文字を選択します。
  • クラスセレクター:要素には、CSSスタイルシートで選択するために複数のクラスを設定できます。 たとえば、<h1 class='header'>.headerで選択できます。 複数の要素に同じクラスを適用することができます。
  • 属性セレクター:特定のタイプの属性が適用されている要素を選択します。 たとえば、input[type='number']でのみ数値を受け入れる入力を選択します。
  • 疑似クラス:現在のCSS状態に基づいて要素を選択します。 たとえば、ボタンのホバー状態をbutton:hoverでスタイル設定します。 詳細については、:target :hover、および:active疑似クラスに関するこれらの以前のチュートリアルを確認してください。
  • IDセレクター:一意のIDを持つ特定の要素を選択します。 各IDには1つの要素しか存在できませんが、クラスは複数の要素に適用できます。 たとえば、<h1 id='mainHeader'>#mainHeaderを選択します。
  • インラインスタイル:インラインスタイルはstyle属性を使用して要素に直接適用されるため、実際にはCSSセレクターを使用しません。 たとえば、<h1 style='color: blue;'>を使用して、ヘッダーフォントの色を直接青にすることができます。

CSSセレクターとその「重み」

上記の各タイプのセレクターには重みがあります。 これらはすべて、4つの主要なグループに分けることができます。

  • 最小の重み:タイプおよび疑似要素セレクター
  • 軽量:クラス、属性、および疑似クラスセレクター
  • 中程度の重量:IDセレクター
  • ハイウェイト:インラインスタイリング

同じ要素に異なる重みのスタイルが適用される場合、より高い重みのスタイリングが適用されます。 均等な重みのスタイルが適用される場合、最後に来るスタイル(スタイルシートの最後に最も近い)が適用されます。 これは、CSS(カスケードスタイルシート)の「カスケード」効果によるものです。

スタイリングされている要素については、重みが最も高い最後の適用可能なスタイリングブロックが要素に適用されます。 ただし、インラインスタイルはCSSセレクターのスタイルよりも優先されます。 💅

同じ重みの2つのセレクターが要素に適用されると、重みの2倍としてカウントされます。 したがって、たとえば、2つのクラスで選択された要素は、CSSの1つだけよりも重みが大きくなります。

.gator.cayman { // two classes
  color: purple;
}

.gator { // one class
  color: purple;
}

私たちのほとんどのWeb開発者がいつか直面する主な問題は、互いに干渉する複数のスタイルを持つことです。 Material UI などのCSSフレームワークを使用している場合は、いくつかのデフォルトスタイルをオーバーライドしようとしている可能性があります。 または、古い(そしてまとまりのない🙈)styles.cssファイルを作成して、スタイルが期待どおりに適用されない理由が明確でないため、特異性を高め続ける必要がある場合もあります。

Web開発の他の場合と同様に、ツールをよく理解すると、ツールがより正確に使用されるようになります。 セレクターのさまざまな組み合わせが特異性にどのように影響するか、そして意図したとおりにスタイルを適用するためのいくつかのトリックを見てみましょう。 🤓

競合するセレクターの問題

CSSを整理するには、セレクターごとに重みが異なることを理解することが重要です。 しかし、何がより高い重みを持っているのかが明確でない場合はどうなりますか?

CSSの2つの完全なブロックがある段落があるとします。1つは3つの一致するクラスを持ち、もう1つはtype属性と2つの一致するクラスを持ちます。

たとえば、3つのクラスとnumberタイプの属性が適用されたこの入力を考えてみましょう。

<input type='number' class='gator cayman reptile'>

これらの競合するセレクターを適用すると(3つの一致するクラスと 2つの一致するクラスと1つの属性)、どちらが適用されますか?

.gator.cayman.reptile {
  color: purple;
}

[type='number'].gator.cayman {
  color: green;
}

この場合、両方のブロックの「重量」は完全に均等です。 属性セレクターとクラスセレクターの重みは同じで、各ブロックには合計3つあります。 それらは均一であるため、CSSのカスケード効果に依存しています。 最後のものが適用され、入力フォントの色は緑になります。🐊

ただし、異なる重みのセレクターが混在している場合、これは少し複雑になります。

入力を更新して、クラスや属性よりも重みが大きいIDを取得しましょう。

<input
  type='number'
  id='gatorInput'
  class='gator cayman reptile'>

競合するスタイルが再びあり、一方にIDを使用し、もう一方にクラス/属性を使用する場合、どちらが適用されますか?

#gatorInput {
  color: purple;
}

[type='number'].gator.cayman.reptile {
  color: green;
}

最初のブロックでは、スタイリングを適用するために1つのIDのみが使用されています。 2番目のブロックには、3つのクラスと属性セレクターがあり、最後に来ます。 2番目のブロックにはより多くのセレクターがありますが、IDセレクターの重みが高く、テキストは紫色になります。 💥

重みの小さいセレクターが複数ある場合でも、重みの大きいセレクターは、重みの小さいセレクターよりも常に優先されます。 🏋

セレクターウェイトトリック

もう少し重みが必要な場合のCSSの1つのトリック(わかりました、ハック💩)は、CSSの同じブロックでクラスを繰り返すことです。

input.gator.gator {
  color: purple;
}

input.gator {
  color: green;
}

最初のブロックはクラス.gatorを繰り返しているだけですが、最初のブロックの重みが2クラスで、2番目のブロックの重みが1クラスであることを知って驚かれるかもしれません。 2つのクラスは1つよりも重みが大きいため、入力テキストは紫色になります。 🚀

このトリックを本番レベルのコードで使用する必要はありません。これは、非常に類似した重みのスタイルが競合していることを示しているためです。 理想的には、これらのスタイルを解決して、より明確に定義する必要があります。 ただし、これは、「機能させるだけ」モードの場合のCSSツールボックスの優れたツールです。 ✨

CSSの特異性に関する会社の例え

特に、CSSにセレクターを追加するという下向きのスパイラルに陥っている場合は特に、特異性が直感に反する場合があります。 特異性について考えるのに役立つと思う1つの方法は、明確な年功序列を持つ会社を考えることです。

優先順位の高い順に(低いものから高いものへ)、当社の役割は次のとおりです。

  • 従業員
  • マネージャー
  • ディレクター
  • VP
  • 1人のCEO(後でCEOに戻ります)

これらの役割をセレクターにマップしてみましょう。

  • 従業員:タイプおよび疑似要素セレクター
  • manager :クラス、属性、および疑似クラスセレクター
  • ディレクター:IDセレクター
  • VP :インラインスタイリング

新しい例を見てみましょう。 この場合、2つのクラスと1つのIDを持つ段落があります。

<p id='gatorParagraph' class='gator reptile'>
  blah blah blah
</p>
#gatorParagraph {
  color: purple;
}

p.gator.reptile {
  color: green;
}

IDのみを使用する1つのブロックと、要素タイプ(<p>)と2つのクラスを使用する別のブロックがあります。 一見、どちらが適用されるかを知るのは難しいかもしれません。

私たちの会社の例えを使用すると、1人のディレクターがテキストを紫色にするように言っています。 一方、従業員と2人のマネージャーが、環境に配慮するように言っています。 取締役は最上級であるため、従業員や管理職の意見に勝るものがあります。 したがって、テキストは紫色である必要があります。

(これが会社で決定を行う方法であるかどうかについてのコメントはありません😉)。

どのスタイルを適用するかの決定をエスカレートする方法として、各ウェイトレベルを検討してください。 同じレベルのセレクターが決定できない場合は、エスカレーションすると、上位のセレクターに決定が与えられます。

原則として、CSSをエスカレートし続ける方法を見つける必要がないように、十分に具体的なCSSを作成することをお勧めします。 IDなどの新しいレベルの優先順位を導入すると、意図せずに他のスタイルを上書きする可能性があることに注意してください。

!重要なのはCEOです

これまでのところ、CSSの特異性について、このアナロジーで当社のCEOが誰であるかについては説明していません。 インラインスタイリングよりも高いものは何ですか? !importantルール!

前と同じ例を使用して、以前は重み/優先度が低かったブロックに!importantを追加しましょう。

#gatorParagraph {
  color: purple;
}

p.gator.reptile {
  color: green !important;
}

!importantを追加すると、常に優先順位が可能な限り最高のレベルにエスカレートされます。 私たちの会社の例えで、私たちは今、ディレクター対を持っています。 従業員、2人のマネージャー、およびCEO。 CEOが紹介されるとすぐに、彼女は提案されている他の何よりも優先することができます。 💣

使用しないでください!重要

!importantルールは滑りやすい坂道であり、CSSスタイルでそれを確認することは、一般に、特異性を再編成する必要があることを示す危険信号です。 他の方法で適用されるCSSルールの残りの部分を削除することによってのみスタイルを設定できる要素が存在することはまれです。

!importantを導入すると、次の例のように使いすぎになることがよくあります。 !importantは互いに打ち消し合い、各ブロックの重量とカスケード効果を理解する必要があります。

#gatorParagraph {
  color: purple !important;
}

p.gator.reptile {
  color: green !important;
}

!importantルールを使用する代わりに、ブラウザーで開発ツールを開いて、新しいスタイルに干渉しているスタイルをよりよく理解してみてください。

問題の原因となっているスタイルがわかったら、同じレベルの重みのセレクターを追加するか、マークアップを更新して別のセレクターを使用することができます。 🌈

!importantを使用すると、必然的に、両方が!importantを使用するCSSスタイルが競合することになります。 🙈

ユニバーサルセレクターとコンビネーター

ユニバーサルセレクター(*)とコンビネーターは、セレクターの重量に影響を与えません。 コンビネータには、子セレクター(>)、一般的な兄弟セレクター(~)、および隣接する兄弟セレクター(+)が含まれます。

たとえば、2つのスパンを持つ段落がある場合、子コンビネータを使用しても、それを使用しない場合よりも特異性が向上することはありません。

<p id='gatorParagraph'>
  <span class='reptile'>eggs</span>
  <span class='reptile'>nest</span>
</p>
#gatorParagraph > .reptile {
  color: purple;
}

#gatorParagraph .reptile{
  color: green;
}

CSSのこれらのブロックは同じ特異性を持っており、子コンビネータは違いがないため、テキストは緑色になります。

CSSの特異性を理解するための最良のビジュアルの1つは、 EstelleWeylによってspecifishityと呼ばれています。 見てみな! 🤓

また、自分で特異度の重みを合計することに熱心でない場合は、特異度計算機が計算を行います。 🥳