CSS
 Computer >> コンピューター >  >> プログラミング >> CSS

CSSの詳細度(Specificity)とは?セレクターの優先順位の仕組みと計算方法を徹底解説

CSSの「詳細度(Specificity)」は、言葉としては少し舌を噛みそうになるうえ、理解するのも一筋縄ではいかない概念です。CSSの中でも特に習得が難しいトピックの一つとされています。この記事では、詳細度とは何か、どのように計算されるのか、そしてセレクターのランク付けがページに表示されるスタイルをどのように決定するのかを解説します。安心してください。読み終える頃には、あなたも詳細度のエキスパートになっているはずです。

「詳細度」とは何か?

CSSの詳細度とは、簡単に言えば「そのセレクターがどれだけ重要か」を表すものです。各セレクターには、その種類に応じて詳細度が割り当てられます。数値が大きいほどセレクターは具体的であり、そのCSSブロックがスタイルの競合に勝つ可能性が高くなります。

詳細度は、カンマで区切られた4つの数字で表現されます。

セレクターの詳細度 = 0, 0, 0, 0

カンマを除いた4桁の数字(0000、0101、1001など)として見た場合、数値が大きいほどより具体的であることを意味します。

セレクターの詳細度ランキング(低 → 高)

それでは、ランクの低いものから順に、さまざまな種類のセレクターを見ていきましょう。

  • *(アスタリスク)

ユニバーサルセレクターです。詳細度は 0, 0, 0, 0。通常、スタイルシートの先頭で目にします。重要度のランキングでは最下位に位置し、ほぼすべてのスタイルがこれを上書きしたり、追加したりできます。

  • >、+、空白文字(子孫結合)、~

結合子(コンビネータ)です。型セレクターやクラスセレクターの子要素・兄弟要素を選択する際によく使われますが、詳細度には一切影響せず、合計値にもカウントされません。否定疑似クラス(:not())も同様に、それ自体は詳細度に加算されません(括弧内の引数セレクターのみがカウントされます)。

  • div、form、ul、li など

これらは型セレクター(タイプセレクター)です。HTMLにおけるタグと呼べるもの全般を対象とします。詳細度は 0, 0, 0, 1 です。結合子で区切って複数の型セレクターを並べた場合は、それぞれの数値が加算されます。

div li {} ⇐ 詳細度は 0,0,0,2
div li p {} ⇐ 詳細度は 0,0,0,3
  • .main-container、.navbar、[type="text"]、:hover

次にランクが上がるのは、クラスセレクター、属性セレクター、疑似クラスセレクターです。

クラスセレクターは先頭のドット(.)で示されます。属性セレクターは型セレクターの隣に角括弧で囲んだ属性を記述します。疑似クラスセレクターは、より具体的なスタイルが必要な特殊な状態の要素のために使われます。これらの詳細度は 0, 0, 1, 0 です。

div.navlink a {}

— この詳細度は 0, 0, 1, 1 です。クラスセレクターが1つ、型セレクターが1つ含まれているためです。

div.header li.list-item-disc button[type="submit"] {}

— この詳細度は 0, 0, 3, 3 です。型セレクターが3つ、クラスセレクターが2つ+属性セレクターが1つ含まれているためです。仮に属性セレクターを外すと、詳細度は 0, 0, 2, 3 になります。23は33より小さいため、詳細度 0, 0, 3, 3 のセレクターが勝ちます。

  • #blue、#hidden など

IDセレクターは、CSSセレクターの中で最も高い詳細度を持ちます:1, 0, 0, 0。ID属性は文書内で一意であるという性質上、CSSでIDを指定する際は、極めて限定的な要素にスタイルを適用していることになります。

div#orange {}

— この詳細度は 1, 0, 0, 1 です。型セレクターとIDセレクターが含まれているためです。それでは、以下の2つのルールのうち、詳細度のルールに従うとどちらのスタイルが勝つでしょうか?

div#orange {
	background-color: orange;
}
div.square {
	background-color: green;
	width: 150px;
	height: 150px;
}
  1. 最初のdivは型セレクターとIDセレクターを持つため、全体の詳細度は 1, 0, 0, 1 です。
  2. 2番目のdivは型セレクターとクラスセレクターを持つため、全体の詳細度は 0, 0, 1, 1 です。

1001は11より大きいため、最初のdivが勝ち、背景色はオレンジになります。これはCSSのカスケード(後から書いたルールが優先される性質)に反する結果である点に注目しましょう。

  • インラインスタイル

インラインスタイルはどこに位置づけられるのでしょうか?実は、IDセレクターよりもさらに具体的です。インラインスタイルは、CSSファイル内のほぼすべてのルールに打ち勝ちます。詳細度において最も重みが大きい存在です。

  • !important ルール

!important キーワードはすべてに打ち勝ちます。最も強力で、それまでにCSSで設定されたあらゆるルールを上書きします。ただし乱用すると保守性が低下するため、使用は最小限にとどめるのがベストプラクティスです。

演習問題

以下のコードには、ランダムなクラス名とID名を持つサンプルコンテナのページがあります。CSSスキルを活かして、特定の要素だけ色を変え、他のdivは元の色のままにする練習をしてみましょう。どのようにCSSルールを書けばよいでしょうか?また、特定の要素を確実に狙うために最高の詳細度が必要な場合、何を利用すればよいでしょうか?コード内のコメントにある問いにも答えてみてください。

<!DOCTYPE html>
<html lang="en">
   <head>
       <meta charset="UTF-8" />
       <meta name="viewport" content="width=device-width, initial-scale=1.0" />
       <title>CSS Specificity</title>
       <style>
           body {
               width: 100%;
               max-width: 800px;
               margin: 0 auto;
           }
 
           main {
               width: 100%;
               height: 800px;
               display: flex;
               flex-wrap: wrap;
               flex-direction: column;
           }
 
           div {
               text-align: center;
           }
           *.square {
               /* この星印(*)は何を意味する?詳細度に影響する?どうやって検証できる? */
               height: 150px;
               width: 150px;
               background-color: black;
               color: white;
               margin: 20px;
           }
 
           div.flex {
               /* このセレクターは.squareクラスと競合する?それとも連携して動作する?
                  ここにwidthとheightを追加したら何が起こる?なぜそうなる?
 
                  これはdivセレクターを上書きする?なぜ?詳細度はどう比較される? */
               display: flex;
               justify-content: center;
               align-items: center;
           }
           div#red {
               /* なぜこちらが勝つ?このdivの詳細度はいくつ? */
               background-color: darkred;
           }
           #red {
               /* 直前のセレクターから「div」を外したら何が起こる?どちらが勝つ? */
               background-color: red;
           }
 
           main > div {
               font-size: 55px;
               font-weight: bold;
           }
 
           div#self-align {
               /* ここでは何が起こっている? */
               align-self: center;
           }
       </style>
   </head>
   <body>
       <main>
           <div id="self-align" class="square flex">1</div>
           <div class="square flex">2</div>
           <div class="square flex">3</div>
           <div class="square flex">4</div>
           <div class="square flex">5</div>
           <div id="red" class="square flex">6</div>
           <div class="square flex">7</div>
           <div class="square flex">8</div>
           <div class="square flex">9</div>
           <div class="square flex">10</div>
           <div class="square flex">11</div>
           <div class="square flex">12</div>
       </main>
   </body>
</html>

まとめ

この記事では、CSSの詳細度について解説しました。具体的には、どのセレクターが他よりも強力なのか、そして実際の詳細度の数値をどのように算出するのかを学びました。一度読んだだけで完全に理解できなくても、落ち込む必要はありません。消化すべき情報量は決して少なくありません。諦めずに手を動かしながら続ければ、必ず理解できるようになります!

  1. CSS Flexbox入門:親コンテナと子アイテムの主要プロパティを徹底解説

    CSS Flexbox(フレックスボックス)モデルは、従来のCSSボックスモデルを改善するために考案されました。Flexboxモデルには、ボックスモデルの主要な要素(margin、padding、border、content)がそのまま含まれていますが、さらに柔軟性が加わり、コンテナ(親要素)の中に子要素を最適な形で配置できるようになっています。 このチュートリアルでは、Flexboxモジュールの基本をわかりやすく解説し、よりレスポンシブなサイト制作に役立てられるようサポートします。 以下は、基本的なFlexboxモデルのデモ用スターターコードです。解説を読みながら、実際にコードを動かして

  2. CSSシェイプ入門:正方形からハートまで図形を自由に描く方法

    それでは、楽しいCSSシェイプを作っていきましょう!すべてのコードは私のCodepenで確認できます。さっそく始めましょう。 長方形と正方形 すべての図形はdiv要素で囲みます。最も基本的な図形は正方形と長方形です。divはデフォルトで、widthとheightプロパティの値に応じて正方形や長方形として表示されるためです。正方形は幅と高さが等しく、長方形は等しくありません。 .rectangle { width: 2rem; height: 4rem; background-color: violet; } .square { width: 5rem; height