【CSS】「詳細度アルゴリズム」について解説!【分かりやすい】
しゅーた(@chibasyuta)です!
この記事ではCSSの「詳細度アルゴリズム」について解説します。
このような方が対象です。
この記事の内容!
- そもそもセレクターとは何か?
- 「詳細度アルゴリズム」とは何か?
それでは内容へ入ります!
そもそもCSSの「セレクター」とは何か?
CSSの「セレクター」とは「どの要素にスタイルを当てるか?」を指定する箇所のことを指します。
「詳細度アルゴリズム」とは何か?
CSSの「詳細度アルゴリズム」とは、異なるセレクターの宣言が競合した場合に「どのセレクターからのスタイルを優先するか?」を決定するアルゴリズムのことを指します。
それぞれのセレクターに「詳細度」が与えられ、競合した場合は「詳細度」が高いセレクターからのスタイルが優先されます。
「詳細度」はどのようにして決まるか?
まずそのセレクターに使われている「idセレクターの数」「クラスセレクター、属性セレクター、疑似クラスセレクターの数」「要素型セレクター、疑似要素セレクターの数」を計算します。
「h1.foo」だったら(0, 1, 1)
「ul li」だったら(0, 0, 2)
「#hoge」だったら(1, 0, 0)
のように(id列, class列, type列)と別々に集計します。
基本的に「詳細度」の数値が高い方が優先される
スタートは「(0, 0, 0)」です。
そこからそれぞれの列に該当する成分があれば、1つずつ足していきます。
「#hoge.foo.box h3.active」だったら、(1, 3, 1)ですね。
最初に「id列」の数値が大きいセレクターが最も優先される
詳細度を決める上で最も重要なのは「id列」の数値です。
「h1.foo」だったら(0, 1, 1)
「ul li」だったら(0, 0, 2)
「#hoge」だったら(1, 0, 0)
この3つだと「id列」の数値が最も高いのは「#hoge」じゃないですか。なのでこれが最も優先されます。
次に「class列」の数値が大きいセレクターが優先される
「id列」が同じ数値だった場合、次に使われるのが「class列」です。
「h1.foo」だったら(0, 1, 1)
「ul li」だったら(0, 0, 2)
この2つは「id列」の数値が同じです。なので「class列」を見ます。
すると、「h1.foo」の方が「class列」の数値が高いので、これが優先されます。
最後に「type列」の数値が大きいセレクターが優先される
「id列」と「class列」の数値が同じだった場合に最後に比べられるのが「type列」の数値です。
「ul li」だったら(0, 0, 2)
「ul li p」だったら(0, 0, 3)
なのでこの2つだったら、「ul li p」が優先されます。
結合子はカウントされない
例えば、「ul > li > .foo」だったら(0, 2, 1)です。
「*」全称セレクターもカウントされない
例えば、「*」だったら(0, 0, 0)です。簡単に上書きできます。
「:not()、:has()、:is()」はカウントされない
「:」コロンから始まる疑似クラスは「class列」にカウントされます。
ですが、「:not()、:has()、:is()」自身はカウントされないので注意してください。
「詳細度アルゴリズム」の範囲外
それは下記の通りです。
「詳細度アルゴリズム」の範囲外!
- 「インラインスタイル」
- 「!important」
「インラインスタイル」
<p style="color: skyblue;">段落です。</p>
他のセレクターよりも「インラインスタイル」が優先されます。
なので、(1, 0, 0, 0)となる感じですかね。
「id列が」の数値がどんなに高くても「インラインスタイル」が勝ちます。
「!important」が最優先
p {
color: skyblue!important;
}
「!important」が最優先です。
宣言の後ろに「!important」と書くと、その宣言が優先されます。
「!important」は「インラインスタイル」よりも優先されます。
まずは詳細度を低く書く
<h1 id="hoge" class="foo">見出しです。</h1>
基本的にCSSのセレクターの詳細度は低くする意識で書くといいと思います。
「idセレクター」など、詳細度が高いものを無暗に使ってしまうと、上書きするのが難しくなるので、できればまずは「要素型セレクター」を使ったり「クラスセレクター」を使うといいと思います。
「属性セレクター」を使って「idセレクター」の詳細度を下げる
<h1 id="hoge" class="foo">見出しです。</h1>
[id="hoge"] {
color: skyblue;
}
「属性セレクター」を使うことで「idセレクター」の詳細度を下げることができます。
「属性セレクター」は「class列」でカウントされるので、「idセレクター」を使うよりも詳細度が下がっていますね!
複合セレクターを使う「#hoge#hoge」
<h1 id="hoge" class="foo">見出しです。</h1>
#hoge#hoge {
color: skyblue;
}
.foo.foo {
color: skyblue;
}
無理やり複合セレクターを使ってあげることで、詳細度を上げることができます。
「.foo.foo.foo」のように何個でもつけることができます。
参考リンク。
仕様書。
https://drafts.csswg.org/selectors/#specificity-rules
MDN。
https://developer.mozilla.org/ja/docs/Web/CSS/Specificity
あわせて読みたい記事。
大学生が夏休みにweb制作で13万円稼ぐまでにやったこと。【経験談】
まとめ
CSSの「セレクター」とは「どの要素にスタイルを当てるか?」を指定する箇所のことを指す。
CSSの「詳細度アルゴリズム」とは、異なるセレクターの宣言が競合した場合に「どのセレクターからのスタイルを優先するか?」を決定するアルゴリズムのこと。
基本的に「詳細度」の数値が高い方が優先される。
最初に「id列」の数値が大きいセレクターが最も優先されて
次に「class列」の数値が大きいセレクターが優先されて
最後に「type列」の数値が大きいセレクターが優先される。
結合子はカウントされない。
「*」全称セレクターもカウントされない。
「:not()、:has()、:is()」もカウントされない。
下記のような場面では「詳細度アルゴリズム」は通用しない。
「詳細度アルゴリズム」の範囲外!
- 「インラインスタイル」
- 「!important」
基本的には詳細度を低く書くことをおすすめする。
この記事が気に入った方は僕のTwitter(@chibasyuta)のフォローもお願いします!
それではこんな感じでこの記事を終わります!
ではまた!