バートリーのさいとうです。
今回は
【HTML・CSS】指定したセレクタのcssが読み込まれない理由を、セレクタの読み込み順から理解する
というテーマを取り上げます。
実務にあたっていると、こんな経験したことありませんか?
「似たようなデザインをしているプロパティを持つセレクタがあったけど、一部分だけ変更して利用したい。でもそのやり方がわからなくて結局新しいセレクタを作ってしまった…」
例えば、以下のコードのように、background-colorだけが異なるdivに対して、このようなcssを振ってしまうことです。
See the Pen by バートリーのさいとう@エンジニア (@bartleysaito) on CodePen.
この書き方だと、同じプロパティを持つセレクタが重複し、コードは長くてぐちゃぐちゃに。
その結果、運用コストが余分に発生します。
同じ悩みを抱えていたそんな僕が、シンプルだけど効果的なhtml, cssのルールを見つけました。
それが、セレクタの読み込み順です。
この記事を読めば
- セレクタの読み込み順を理解できる
- 部分的に既存のセレクタを上書きして活用できる
- 実務レベルのcssの当て方を理解できる
この記事を読んだあとには、あなたのコードから余分なコードが減り、綺麗で理解しやすいコードをかけるようになっているはずです。
フロントエンド専門ではない僕だからこそ、皆さんの視点に立って、わかりやすく解説します。
ぜひ最後まで読んでみてください。
二つの優先順位
それでは、早速結論をお伝えしようと思います。
セレクタの優先順位付けには、二つ大きなルール(基準)が存在します。
- 抽象度
- 読み込みの順番
一つずつ紹介していきます。
抽象度:「どの要素の何id?」が最強
早速意味のわからないことを言ってすみません。
先にコードをお見せすると
p#xyz {color:blue;} /*要素を特定したidセレクタ*/
#xyz {color:green;} /*要素を特定しないidセレクタ*/
p.abc {color:yellow;} /*要素を特定したclassセレクタ*/
.abc {color:orange;} /*要素を特定しないclassセレクタ*/
p {color:red;} /*タイプセレクタ*/
* {color:purple;} /*全称セレクタ*/
(参考)
上に行くほど、読み込みの優先順位が上がります。つまり、他のセレクタより優先して適用されるということです。
逆に、下に行くほど読み込みの優先順位は下がります。
これは、「抽象度の違い」という言葉が一番理解しやすいかと思います。
抽象度=どの要素を指しているかの解像度
上に行けば行くほど、「htmlの中で、どの要素を指し示しているのか?」の解像度が上がっていきます。
例えば、タイプセレクタはpとかdivとか、要素の種類はわかりますが、特定のどの要素なのかはわかりません。
対して、要素を特定して、かつidが振られているとなると、まさにこれ!って感じがしますよね。
ちなみに、classとidでidの方が解像度が高く設定されています。(つまり抽象度が低い)
理由は、idが同じファイル内では一意性を持つからです。
classは重複してもいけど、idは重複しちゃダメだよ、ということです。
よって
- 要素を特定したidセレクタが、最も優先して表示される
- 全称セレクタは、一番優先順位が低い。
これを理解しているだけでもある程度は自由にセレクタを指定できるようになります。
しかし、次に説明するもう一つの順番を理解していると、余計なcssを作成することなく、更に綺麗で読みやすいコードを書くことができます。
読み込みの順番:同じ優先順位の時は、後ろのやつが上書きを行う
では、もし同じ優先順位のセレクタがあったらどうでしょう。
この場合、最後に指定したセレクタが優先されます。
以下の例を見てください。
See the Pen by バートリーのさいとう@エンジニア (@bartleysaito) on CodePen.
二つ目のdivに二種類のclassが適応されています。
適応されているのは、cssファイルで後に記述されているbox_class_laterの方ですね。
このように、同じ優先順のクラス同士だと、基本的には後に記述されているものが優先して読み込まれます。
「上書きをしている」という言葉がぴったり当て嵌まりますね。
抽象度 vs 読み込みの順番
ここまで、抽象度と読み込み順がセレクタの優先順位に影響を与えるという話をしてきました。
では、抽象度と読み込み順、どちらが優先されるのでしょうか。
答えは、抽象度です。
以下の例を見てください。
See the Pen by バートリーのさいとう@エンジニア (@bartleysaito) on CodePen.
box_idはcssファイルの一番最初に書かれてます。つまり、読み込みの優先順位は最も下になるはずです。
しかし、idという抽象度の低いセレクタが振られているため、結果box_idのcssが適応されています。
この理由については、以下の記事を参考すると、点数性になっていることがわかります。
その説明が非常にわかりやすかったので、是非こちらの記事も読んで理解を深めてください。
書く場所と!important
しかし、さらに優先順位を上げることも可能です。
1つが、書く場所です。
.box{style: "width: 100px;height:100px"}
このように、直接html(haml)にstyleを付与するのが、最も優先順位を高められます。
もう一つは、!importantです。
.box{
width: 1000px !important;
}
このように!importantを利用すると、最優先でこのセレクタを適応させることができます。
しかし、それぞれ
- 直接style: レスポンシブにならない
- !important: 他のセレクタに影響が跳ねる危険性があり、多用は危険
というデメリットもありますので、利用の際は気をつけましょう。
まとめ
いかがだったでしょうか。
僕はフロントエンドエンジニアではないので、完璧な説明とはいきません。が、その代わり丁寧に説明してみました。
このブログは、月に15本を目標に、実務から学んだプログラミングのあれこれを発信しています。
誰かのためになれば、嬉しいです。
最後まで読んでいただき、ありがとうございました。
それでは。