誤解しているかも! CSSの詳細度について、よくある誤解を解説
Post on:2024年5月23日
CSSの詳細度とは、(0,0,2)
や(1,0,0)
など3つの数字でスタイルを適用する際の優先度を決めるブラウザのアルゴリズムです。要素に対して複数のCSS宣言があり、そのプロパティや値が競合している場合、詳細度が高いものが優先されます。
このCSSの詳細度について、よくある誤解を紹介します。
Misconceptions about CSS Specificity
by Bramus!
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
はじめに
CSSの詳細度(Specificity)、ひいてはカスケード(Cascade)に関する記事が公開される度に、私はとても興奮します。なぜなら、それは誰もが知っておくべきCSSの中核となる概念だからです。詳細度に関する記事は多ければ多いほど、素晴らしいと思います。
しかし、残念なことに完全に間違っている記事に遭遇することもあるため、ときどき眉をひそめてしまうことがあります。
この記事ではそういった混乱を少しでも取り除くために、CSSの詳細度についてよくある誤解を解説します。
詳細度の誤解 1: 詳細度は10進数である
これは多くの記事で見かける間違いです。詳細度を10進数のスコアで記載したり、クラス・セレクタが「10ポイント追加される」と記述されてたりします。これは「それぞれ1ポイント」を持つ11個の要素セレクタが「10ポイント」しか持たない1つのクラスセレクタに勝つことを意味するので、不正確です。
詳細度はA
, B
, C
の3つのコンポーネントを持つトリプルです。A
, B
, C
の値は、使用するセレクタの種類によって異なります。
A
:id
セレクタによる重みの値B
:class
セレクタによる重みの値C
: 要素型セレクタによる重みの値
多くの場合、CSSの詳細度は(A,B,C)
表記が使用されます。たとえば、(1,0,2)
と記述されます。また、A-B-C
という表記も使用されます。
セレクタの詳細度を計算できるJavaScriptライブラリ「Specificity」があります。これを使用すれば、インタラクティブに詳細度を表示できます。デモページでその動作を確認できます。
See the Pen
Calculate Specificity with @bramus/specificity
by coliss (@coliss)
on CodePen.
CSSの詳細度は、3つのコンポーネントを順番に比較することによって比較されます。A
値が大きいほど詳細度は高くなり、A
値が同じの場合はB
値が大きいほど詳細度は高くなります。B
値も同じの場合はC
値が大きいほど詳細度は高くなります。すべての値が同じの場合は、詳細度は等しいことになります。
コードでは次のようになります。
1 2 3 4 5 6 7 8 9 |
const compare = (s1, s2) => { if (s1.a === s2.a) { if (s1.b === s2.b) { return s1.c - s2.c; } return s1.b - s2.b; } return s1.a - s2.a; }; |
たとえば、(1,0,0)
のA
値(1
)は、(0,10,3)
のA
値(0
)より大きいので、(1,0,0)
は(0,10,3)
よりも詳細度が高いということになります。
先頭が0の場合に0を削除することで、3つで構成されるトライアドを10進数で表すことはできますが、それには一連の課題があります。最終的に得られる数値は桁数が異なり、読み取りや解析ができなくなるため、先頭の0は保持する必要があります。
私からのアドバイスは、しないでください、です。
【訳者注】たとえば、(1,0,0)
を100、(0,10,3)
を103と記述してしまうと、どちらの詳細度が高いのか間違えてしまいます。
混乱の原因は、次の通りです。
Selectors Level 3の仕様では、次のように記載されていました。
a-b-c
の3つの数値(基数が大きい数値体系で)を連結することで、詳細度が得られます。
この仕様には「基数が大きい数値体系で」と注意書きがあるにもかかわらず、この条項は無視されているようです。ほぼ15年が経過した現在でも、わたし達はこの条項に固執しています。
また、「説明するのが簡単だから」という理由で、そのような説明を使い続けているブロガーもいます。それは事実かもしれませんが、人々に間違ったことを伝えていることになります。後で学び直すということは、はるかに困難です。
詳細度の誤解 2: style属性で詳細度が追加される
style
属性を使用すると「詳細度が1000ポイント追加される」という記述をよく目にします。しかし、style
属性の評価はカスケードの初期ステップであるため、これは正しくありません。style
属性は詳細度にまったく関係がありません。
カスケードのステップ(style
属性は強調表示)
詳細度(Specificity)はその後の後です。
混乱の原因は、次の通りです。
CSS2の時代(2011年ごろ)は、確かにそうでした。CSS 2.1の仕様では、詳細度は(A,B,C,D)
の4つで構成されており、style
属性はA
のコンポーネントでした。
CSS3以降、これはなくなりました。
詳細度の誤解 3:!importantで詳細度が高くなる
!important
を宣言につけると「詳細度が10000ポイント追加される」という記述もよく目にします。!important
を使用すると、宣言が別のオリジンに配置されるため、これは正しくありません。オーサースタイルで!important
を使用すると、宣言は通常のオーサー宣言(Normal author declarations)から重要なオーサー宣言(Important author declarations)に移動します。
通常(Normal)と重要(Important)のオーサー宣言は強調表示)
オリジンと重要性は、カスケードで最初にチェックされる基準です。詳細度はそのずっと後に現れます。
混乱の原因は、次の通りです。
この件については仕様にはその痕跡が見つかりませんでした。ある日誰かが思いついたものだと思われます。一見すると、筋が通っているように思われますが、カスケードの3つ前の基準である「コンテキスト」「要素付きスタイル」「レイヤー」をスキップします。よろしくないですね。
終わりに
CSSの詳細度とカスケードについて詳しく知りたいときは、CSS Day 2022で行った講演を見ることをお勧めします。
その講演で使用したスライドもあります。
sponsors