Edited at

エンジニアはもう一度CSSとちゃんと向き合ってみよう - 詳細度編


詳細度


WHAT

CSSには詳細度(Specificity)という概念があります.


詳細度は、どのプロパティ値が最もある要素に関係があり、適用されるかをブラウザが決定する手段です。

詳細度 - CSS | MDN


簡単に言うと,「スタイルが重複したとき,どのスタイルを優先するか」の優先度を定量評価したものになります.

詳細度はa, b, cのようなカタチで表されます.

細かい説明するのは面倒なので,ざっくりと以下にリストアップします.


  • 全称セレクタ: a=0, b=0, c=0


    • *



  • 要素,擬似要素: a=0, b=0, c=1



    • li, ::before, ::first-line, etc.



  • クラス,擬似クラス,属性: a=0, b=1, c=0



    • .classname, :first-child, [type=password], etc.



  • id: a=1, b=0, c=0


    • #idname



あとは各桁ごとに雑に足せば詳細度の出来上がり!


Quiz: 表示される文字は何色?


Q1

Q1 解説

#i1 { color: red; }

.c1 { color: blue; }

<p id="i1" class="c1">ピザ食べたい</p>


Q2

Q2 解説

.c1 > .c2 { color: red; }

.c1 .c2 { color: blue; }

<p class="c1"><span class="c2">寿司食べたい</span></p>


Q3

Q3 解説

#i1 { color: red; }

.c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11 { color: blue; }

<p id="i1" class="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11">

ビール飲みたい
</p>


Q4

Q4 解説

#i1 #i2 { color: red; }

#i1 .c1.c2.c3.c4.c5.c6.c7.c8.c9.c10.c11 { color: blue; }

<p id="i1">

<span id="i2" class="c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11">
おなかすいた
</span>
</p>


解説


A1

解説するまでもないですね,赤です.

.c1より#i1のほうが詳細度が高いです.


A2

青です.

直下セレクタ>,隣接セレクタ+は詳細度に影響を及ぼしません.

この場合だと詳細度が同じ0.2.0であるため,後から定義されたほうが優先されます.


A3

赤です.

詳細度は"100 v.s. 110"ではなく,"1.0.0 v.s. 0.11.0"なので,#i1が優先されます(後述).


A4

これも赤です.

詳細度は2.0.0と1.11.0なので,#i1 #i2が優先されます.


よくある勘違い


詳細度ってポイント制じゃないの?

多くの解説サイトではポイント制として表現されています.要素は1ポイント,クラスは10ポイント,idは100ポイント,みたいなやつですね.

大きく外れているわけではないですが,この考え方には罠があります.

先ほどのQ3を例にするとよくわかると思います


  • ポイントで考えた場合



    • #i1 #i2: 100 + 100 = 200


    • #i1 .c{1..11}: 100 + 10 * 11 = 210



  • バージョン番号っぽく考えた場合



    • #i1 #i2: 2.0.0


    • #i1 .c{1..11}: 1.11.0



単純に大小比較をしてしまうと,結果がひっくり返って見えちゃいますね.

こういうわけで,詳細度はバージョン番号っぽく考えることをオススメします.


インラインスタイルは?

HTMLの要素中に属性値として定義するタイプのやつですね: style=""

これは古い解説サイトでは1000ポイントと言われていることが多いです.

が,それは遥か昔,古の時代の話です.

CSS3系ではなかったことになっています.

IE8なんてなかった.


!importantは?

「ここには絶対このスタイルを適用したい!」というとき,!important宣言を付与することでそのスタイルの優先度を最大にすることが出来ます.しかし,!importantはあまりにも優先度が高いため,あとからスタイルを上書きしたくなったときにとんでもない茨の道に迷いこむことになります(!importantを打ち消すには!importantをぶつけたうえで詳細度で勝たなければならない… これが繰り返されるとどうなるのか…).

あらゆるところで叫ばれていることではありますが,原則として!important宣言の使用は避けましょう


ここスタイル反映されないし,idつかっちゃえ〜〜

これもなるべく避けましょう.

#idname!importantほどではありませんが,詳細度が高いうえに,同一ページ内での複数回の利用が許されないなど小回りも聞かないです.

上書きしたくなったときにどうしようもなくなって!important使うハメになった経験,ありますよね?

特に,使いまわすスタイルとかに入れるのは絶対やめましょう.わけわかんなくなります.

htmlbody等のルートになる要素につけてページ固有のスタイル〜〜 ならまだわからなくもないですが…)


Conclusion


  • 詳細度はバージョン番号っぽく考える


  • #idnameはなるべく使わず.classnameや属性でなんとかする

  • インラインスタイルはやめましょう(style=""


  • !importantは絶対にやめましょう


References