「!important」無意味に使っていませんか? ~CSSの詳細度について~

こんにちは。
4月からあっという間に2ヶ月経っていることに驚きを隠せない、古屋です。
いきなりですが、
CSSをコーディングする中で
「インライン記述はしてはいけない!」
とか
「!importantは使わないで!」
というような規約を見たり、言われたことはないでしょうか?
その場では何となく他のルールに影響を与えてしまうんだななんて理解していたのですが、
一度ちゃんと理解した方が良いなという場面があったので、
今回はCSSの詳細度について改めて調べてみようと思います。
なお、レベルとしては当たり前レベルの内容になるかと思いますのでご了承ください。
優先順位のルール
そもそもCSSが適用される順番の前提として以下の2つのルールがあります。
- 読み込み順
- 詳細度順
読み込み順
文章を読むのと同じようにCSSもあとに書かれたルールが適用されます。
詳細度順
CSSには詳細度という概念があり、スタイルを指定するセレクタの種類や数によって計算されます。
なお、セレクタの種類による優先度の高さは、
上から高い順に
- !important
- インライン属性
- idセレクタ
- Classセレクタ = 属性セレクタ = 擬似クラス
- 要素セレクタ = 擬似要素
- ユニバーサルセレクタ
となっています。
(なぜ各セレクタの順位が決定されるのかは今回は割愛します・・・)
セレクタの個数が増えることで詳細度も上がりますので、
idセレクタ × 2 > idセレクタ × 1
となるということですね。
ここで注意しなくてはいけないのは、
詳細度の計算は単なる加点方式ではないということです。
よく出回っている情報として、
Id はひとつ 10ポイント
Classはひとつ 1ポイント
のように加算していき、大きい方が優先されるという情報ですがこれは正確には正しくありません。
この方法で計算すると以下のような場合にどのような結果になるでしょうか。
<p id="id1" class="cl1 cl2 cl3 cl4 cl5 cl6 cl7 cl8 cl9 cl10 cl11">何色になるか</p>
//1
#id1 {
color: blue;
}
//2
.cl1.cl2.cl3.cl4.cl5.cl6.cl7.cl8.cl9.cl10.cl11 {
color: green;
}
1はセレクタとしてidをひとつ指定しているので10ポイント
2はclassを11個指定しているので11ポイント
よって2が優先されてpタグの文字は緑になるはずです。
ですがこれを実際に動かしてみると文字色は青になります。
これがたとえclassを1000個指定しても文字色は青になるのです。
つまり詳細度を計算するにあたって
Classが何個集まっても、idひとつには決して勝つことができないと言えます。
このことは以下の詳細度を計算できるサイトなどで計算してみると明らかです。
CSSにおける詳細度はバージョン番号を思い浮かべると理解しやすいかもしれません。
上の例では
1は 0.0.1.0
2は 0.0.0.11
なのでclassを1000個指定しても
0.0.0.1000
となるだけなのでidには勝てないのですね。
詳細度が高くなるとどうなるか
詳細度が高いということがCSSにおいて優先されるということが分かりましたが、
では優先度を上げることがCSSを書く際に重要なのでしょうか。
これは全く逆で、詳細度を無駄に高くしないというのが
CSSにおいてはメンテナンス性や拡張性を高めることに繋がります。
おそらく皆さんも追加したルールがうまく適用されないという経験があるのではないかと思いますが、
それは既に書かれているルールの方が詳細度が高いからということが原因かもしれません。
かといってそのHTMLにどんなルールが当たっているかは、一目で把握できるわけではありません。
特にプロジェクトが大きく、複雑になればなるほど特定が難しくなるのは想像に難くないでしょう。
なので冒頭でも述べた通りインライン記述や!importantを使ってしまうと無駄に詳細度が上がってしまうということで禁止されることが多いのですね。
では詳細度を無駄に高めないコーディングを日頃から意識するにはどうしたら良いでしょうか。
簡単なものを3つ紹介します。
1, 要素セレクタを省略する
例えば以下の例では、aタグのundecidedクラスを指定していますが、
本当にaタグ要素を指定する必要があるのでしょうか。
a .undecided {
color: #f5d500;
}
a .undecided:hover {
color: white;
}
調べてみると、undecidedクラスはaタグにしか付与されていないことが分かりました。
よってこれは、
.undecided {
color: #f5d500;
}
.undecided:hover {
color: white;
}
と要素セレクタを省略しても問題はなく、詳細度を下げることができました。
2,セレクタを短くする
意図して指定していないセレクタの場合は省略しましょう。
.sidebar ul.tags-box li a {
display: inline-block;
text-decoration: none;
...
}
.sidebar .tags-box a {
display: inline-block;
text-decoration: none;
...
}
不要なセレクタを省略することは、単純に詳細度の問題を解決するだけではなく、
特定の要素への依存を減らすことになるので、移植しやすくなるというメリットもあります。
3,セレクタを限定的にする
子セレクタを使用する場合、ルールの範囲を限定的にすることができるので
単純にコード量が減ることによって詳細度が高くなる事を抑えたり、他のルールへの影響を抑えることができます。
.box > a {
display: inline-block;
text-decoration: none;
...
}
また最後に、上記のこれらの例はクラスを定義してクラスセレクタを使う事で詳細度の問題を一発で解決できる場合もあります。
もちろん無意味にクラスを増やして同じようなルールが散見されるような状態はかえって良くないですし、
既存のルールにも気を回す必要が出てくることもあるので注意は必要ですが、
うまく使えば様々なメリットがあるのは間違いなさそうです。
今回はここまでにしようと思いますが、
CSSは調べてみるととても奥が深いです。
皆さんも少し意識してCSSに触れてみてはいかがでしょうか。