「サンプルの CSS をコピペしたのにうまく反映されない!」
そんなときにチェックしてほしい CSS の優先順位。本日は最終回です。
前回までにご紹介してきた話に加え、今度は親要素や疑似要素をからめたときにどうなるのか、というのを考えてみましょう。
また、総まとめとしてCSS の点数計算を解説したいと思います。
Headline
いろいろな指定ができるCSS
HTML の構造を以下のようにします。
<div id="sample-wrap"> <div id="sample-main"> <div class="sample-inner"> <p class="colorful">ここは何色?</p> <p class="colorful2">ここは何色?</p> <p>ここは何色?</p> </div> </div> </div>
イメージ図はこんな感じです。
段落 <p> で囲まれたテキストが 3 つありますが、文字色を変えたいと思った時にどのような指定が考えられるでしょうか。
タイプセレクタで指定する
まず、すべての文字を赤色にしたいとき。単純にこんな指定ができます。
p { color: red; }
前回ご紹介した「タイプセレクタ」というものですね。
ここは何色?
ここは何色?
ここは何色?
つぎに、3 つの段落それぞれで色を変えてみましょう。
class で指定する
一行目を赤、二行目を緑、三行目を黒にしてみます。
p { color: black; } .colorful { color: red; } .colorful2 { color: green; }
ここは何色?
ここは何色?
ここは何色?
<p> の基本色を黒とし、クラス名ごとに色を切り替えます。
こちらも前回紹介しましたが、「 class > タイプ」という力関係なので、クラス名で指定されている値が優先して反映されます。
疑似要素で指定する
疑似要素を使って「最初の行」と「最後の行」の色を変えることもできます。
p { color: green; } p:first-child { color:red; } p:last-child { color:black; }
ここは何色?
ここは何色?
ここは何色?
基本色を緑とし、最初の行を赤、最後の行を黒としています。
前回はご紹介しませんでしたが、疑似要素もタイプセレクタより力が強いことがわかりますね(厳密に言うとちょっと違いますが、後述します)。
親要素がからむとスンナリいかないカスタマイズ
さて、このようにイチから仕上げていくのであれば、あれこれ試行錯誤しながらでも思うようにスタイリングしていくことができます。
でも実際は、すでにでき上がっているものをカスタマイズしていくことが多いですよね。この場合そうスンナリいかないことがあるのです。
その原因が「親要素」。
たとえば、こんな記述があったとします。
.sample-inner p {color: black;}
これは「sample-inner の中にある <p> の文字色を黒にする」という指定です。
こうなると、ただクラス名や疑似要素を使っただけでは思いどおりにいきません。
たとえクラス名を指定したところで…
.sample-inner p { color: black; } .colorful { color: green; } .colorful2 { color: pink; }
全部黒になってしまいます。
ここは何色?
ここは何色?
ここは何色?
「コピペした CSS がうまく反映されない!」というのは、これが多いんですねー。
では、この回避策を考えてみましょう。
もともとの記述を書き換える
「段落 <p> の文字色は黒じゃなく薄いグレーがいい!」
そんなときは、もとの記述を書き換えてしまえば解決します。
.sample-inner p { color: #555; }
失敗したときのために、もとの記述はコメントアウトして残しておくのもよいでしょう。
/* .sample-inner p { color: black; } */ .sample-inner p { color: #555; }
この場合コメントアウトしなくても、レベルが同じですから後から書いたものが優先されます。
でも、そうしてどんどん追記していくとわけがわからなくなりますし、不要な指定が多いほど表示速度が遅くなってしまうのであまりオススメしません。
親要素を合わせる
もとの記述を書き換えるだけでは、指定箇所の文字色を変えることができません。
そんなときは、親要素を合わせてあげましょう。
.sample-inner p { color: black; } .sample-inner .colorful { color: green; } .sample-inner .colorful2 { color: pink; }
こうすることでそれぞれの指定が効くようになります。
ここは何色?
ここは何色?
ここは何色?
レベルを上げる
前回、「 id > class 」という力関係をご紹介しました。
.sample-inner は #sample-main という要素で囲まれているので、これを使うこともできます。
.sample-inner p { color: black; } #sample-main .colorful { color: green; } #sample-main .colorful2 { color: pink; }
よりレベルを上げるなら、さらに上の親要素を使って指定することもできます。
.sample-inner p { color: black; } #sample-wrap #sample-main .colorful { color: green; } #sample-wrap #sample-main .colorful2 { color: pink; }
さらにクラス名も追加してレベルを上げてみます。
.sample-inner p { color: black; } #sample-wrap #sample-main .sample-inner .colorful { color: green; } #sample-wrap #sample-main .sample-inner .colorful2 { color: pink; }
どうせなら要素を特定してもっと…
.sample-inner p { color: black; } div#sample-wrap div#sample-main div.sample-inner p.colorful { color: green; } div#sample-wrap div#sample-main div.sample-inner p.colorful2 { color: pink; }
ここまでガチガチに固めると、柔軟性が失われてカスタマイズしづらくなりますね。また、この場合もわずかながら表示速度に悪影響を及ぼします。
通常はこんな指定をしませんが、「こんなこともできる」ぐらいで覚えておいてください。
ただ、このガチガチを簡単に超えることもできるのです。
インラインで指定する
第一回目に「スタイルをどこに記述するかで優先順位が変わる」という話をしましたが、たとえ外部スタイルシートにガチガチに固めた指定があっても HTML タグに直接入れた指定のほうが強くなります。
CSS は上記のガチガチ。
.sample-inner p { color: black; } div#sample-wrap div#sample-main div.sample-inner p.colorful { color: green; } div#sample-wrap div#sample-main div.sample-inner p.colorful2 { color: pink; }
でもインラインで「赤」と「青」を指定すると…
<div id="sample-wrap"> <div id="sample-main"> <div class="sample-inner"> <p class="colorful" style="color: red;">ここは何色?</p> <p class="colorful2" style="color: blue;">ここは何色?</p> <p>ここは何色?</p> </div> </div> </div>
ここは何色?
ここは何色?
ここは何色?
おお、インライン強し。
しかしこのインラインすら超えることができます。
どこまで強くなるんだサイヤ人
!important を使う
たとえインラインで文字色が指定されていても
<div id="sample-wrap"> <div id="sample-main"> <div class="sample-inner"> <p class="colorful" style="color: red;">ここは何色?</p> <p class="colorful2" style="color: blue;">ここは何色?</p> <p>ここは何色?</p> </div> </div> </div>
CSS がガチガチに書かれていても
.sample-inner p { color: black; } div#sample-wrap div#sample-main div.sample-inner p.colorful { color: green; } div#sample-wrap div#sample-main div.sample-inner p.colorful2 { color: pink; }
たった一行追加するだけで
.sample-inner p { color: black; } div#sample-wrap div#sample-main div.sample-inner p.colorful { color: green; } div#sample-wrap div#sample-main div.sample-inner p.colorful2 { color: pink; } p { color: yellow !important; }
すべて黄色になります。
ここは何色?
ここは何色?
ここは何色?
今までの説明は何だったのか、というぐらいの最終奥義。
自動的に挿入されるアフィリエイトパーツなんかにインラインで指定があって、どうやっても回避できそうにない、というときはこれで対応するのが早いですね。
また、WordPress のプラグインをたくさん入れていて外部スタイルシートがたくさんある…、という場合も有効です。
ただ最終奥義ですから、何度でも撃つものではありません。ここぞというときに使いましょう。
CSSの優先順位は点数で計算されている!
さて、長々と 3 回にわたって解説してきましたが、これらの優先順位はブラウザが「点数」を計算して反映しています。
まず、以下のように「A」~「D」の 4 クラスがあるとイメージしてください。
クラス | セレクタ |
---|---|
A | インライン |
B | id |
C | class 属性セレクタ 疑似クラス |
D | タイプセレクタ 疑似要素 |
これを「A.B.C.D」と並べて、それぞれの個数を調べます。
参考Calculating a selector’s specificity
ちょっとわかりづらいので、指定例をご覧ください。
指定例 | A | B | C | D | 点数 |
---|---|---|---|---|---|
* | 0 | 0 | 0 | 0 | 0.0.0.0 |
p | 0 | 0 | 0 | 1 | 0.0.0.1 |
p:first-child | 0 | 0 | 0 | 2 | 0.0.0.2 |
.colorful | 0 | 0 | 1 | 0 | 0.0.1.0 |
p.colorful | 0 | 0 | 1 | 1 | 0.0.1.1 |
#sample-wrap | 0 | 1 | 0 | 0 | 0.1.0.0 |
div#sample-wrap | 0 | 1 | 0 | 1 | 0.1.0.1 |
style=”color:red;” | 1 | 0 | 0 | 0 | 1.0.0.0 |
たとえば、3 行目の「p:first-child」。
これは、「p」というタイプセレクタと「:first-child」という疑似要素の 2 つから成り立っています。どちらも D クラスに属しているので、点数は「0.0.0.2」となるわけですね。
この点数はバージョン表記のようなもので、たとえばクラス名が 12 個あれば「0.0.12.0」ということもあり得ます。しかし、どんなに個数を集めてもひとつの id 「0.1.0.0」にはかないません。
こうして見ると、なぜ「#sample-wrap」よりも「div#sample-wrap」のほうが強いかわかると思います。div の「0.0.0.1」ぶんが加算されて優位になる計算です。
ちなみに、1 行目の「*」は全称セレクタというもので、すべての要素にスタイルを適用したいときに使います。以前はデフォルト値をリセットする指定でよく使われていました。
* { margin: 0; padding: 0; }
今は表示速度が遅くなるという観点から、使う人は減ったようです。
まとめ
今までの話をすべてまとめてみましょう。
- CSS を書く場所で強さが変わる
- 優先順位は点数計算ではじき出される
いちいち点数計算せずとも、カスタマイズを繰り返しているうちに感覚でわかってくるでしょう。
表示速度や柔軟性という問題はあるものの、要は思ったとおりに指定が反映されればよいわけで、個人ブログならそこまで固く考えなくてもいいんじゃないかなーと思います。
もし壁にぶつかることがあったら、「そういえば優先順位ってあったな」とこの記事を思い出していただければ幸いです。
それでは、また。