「CSSの指示が効かない。どうして?」
「CSSが効かなかった。修正に時間がかかりすぎる。」
正しいCSSの設定が効かないことがよくありますし、「効かない」ことをどうにかしようとして、更に設定が複雑になり、収集がつかなくなったことはありませんか? この経験は初学者が必ず通る道です。ただ、この苦痛はできるだけ避けたいものです。そこで、この記事では知っておいて欲しい「優先順位」の考え方と「!important」の使い方をご紹介します。この知識があれば、CSSの書き方が変わりますし、問題が発生した時の解を自分で導き、必要以上に解決に時間がかることがなくなるはずです。
この記事は、CSSの初学者向けに書いていいます。経験者を想定した記事ではありません。
CSSが効かない状況
まず、どのような時にCSSの指示が効かなくなるかを知っておきましょう。CSSの記載ミスを除き、一般的には以下のパターンがあります。
- HTMLが長く、複雑なコードのため、単純なCSSのセレクタ構成でCSSが効かず、結果、多数のclassを繋げて、セレクタを構成して問題を解決したが、優先順位が変わってしまったため、その他のCSSが効かなくなった。
- 同じclass名を複数作ったため、セレクタが重複してしまい、それに気づかず同じセレクタを使用し、別の指示を出した場合、CSSが効かなかった。
- テンプレートを購入し、それを元にデザインをする場合(他人が書いたコードに手を加える場合)、詳細なセレクタ設定がされており、単純なCSSの指示が効かなかった。
注意点は、「他人のコード」を使用する場合です。つまり、「github」や「snipet」などから他人が書いたコードをコピー&ペーストして、使用する場合、あるいは、デザインのベースとなるテンプレートをカスタマイズする場合です。他人の書いたCSSの指示を書き換える場合があります。その際、他人の指示が詳細に記述されている場合は(以下の画像参照。CSSを効きやすくするため、class名を連続させ、セレクタの記述を詳細なものとしている)、単純な変更だけではCSSが効かない場合が多々あります。
このようなカスタマイズの際、便利な解決として『「!important」をCSSプロパティの値の後ろにつけて解決すればいいよ』と、と教えてくれる人がいますが、注意です。「!important」を簡単に扱うべきではありません。
「!important」とは?
CSSの指示を効かせるための手段として「!important」があります。これは、何よりも優先してCSSの指示を効かせるやり方で、事実、非常に効果的です。書き方は以下のようにCSSプロパティに記載します。つまり、「;」の前に「!important」を置くだけです。
[code lang=”css” highlight=”2″]
.セレクタ{
プロパティ名: 値!important;
}
[/code]
試しに効果を見てみましょう。以下のようなhtmlを設定します。
[code lang=”html” highlight=”2″]
<div class=”sample”>
<h1>これはサンプルです。</h1>
</div>
[/code]
次に、CSSに2つの異なる設定を行います。下記では「h1」の色指定を一つは、「青」もう一つは「オレンジ」で指示しています。
[code lang=”css” highlight=”2,6″]
.sample h1{
color: blue;
}
.sample h1{
color: orange;
}
[/code]
一般的にCSSの指示は、下の方が優先されます。そこで、色の表示は「オレンジ」となります。
では、これを「!important」を使って、優先的に「青」を表示させましょう。
[code lang=”css” highlight=”2″]
.sample h1{
color: blue!important;
}
.sample h1{
color: orange;
}
[/code]
ブラウザの表示が「オレンジ」から「青」に変わりました。このように、優先的に表示させたいプロパティに対して「!important」を設定するだけで、瞬く間にそれが優先されるのです。
「!important」は最後の手段
「!important」は必要最小限の使用を!
私も最初にこれを教えられ、頻繁に使っていましたが、使いすぎると、問題が発生します。つまり、「!important」が指定されたプロパティよりも、更に優先したいプロパティがあれば、それにも「!important」をつけることになります。このケースが繰り返されると、CSSファイルには「!important」が増えていき、どの要素を優先させるべきか、ブラウザが混乱してしまいます。「!important」の指定数に制限はありませんが、本当に必要な「!important」がわからなくなるため、頻繁に使用するべきものではありません。
「!important」は、CSSに非常に強く指示を出せる効果的手法ですが、乱用は禁物です。あくまで、最後の手段と考えてください。乱用によって、逆にCSSが効かなくなることがあることは覚えておいてください。
別の方法をまず検討する
では、どうすればよいのでしょうか。これを解決するために、CSSが効く「優先順位」についての知識を持ってください。この知識があれば「CSSが効かない」問題を「優先順位」に沿った記述に変えることで、解決することが容易になります。
CSSが反映される優先順位
CSSの同じセレクタに対して、同じプロパティの値があった場合には、ブラウザはどれを優先するかの独自のルールを備えています。以下の図では、順位が下がるにつれて、優先順位も下がります。また、以下以外にも、「ユーザーが設定したCSS」というものがあります。これは、まず使用する機会が少ないですので、一旦省いて説明しています。
順位 | 優先度 | セレクタの種類 | 説明 |
---|---|---|---|
1 | CSSファイル内のメディアタイプの指定 | – | (例)”link media=”screen” rel=”stylesheet” href=”/style.css”/@media screen and (max-width: 768px) style要素内にmedia属性があれば、あるいは、CSSファイル内に@mediaがあれば、最も強く優先されます。 |
2 | 作成者がHTML文書に記述したCSS | – | (例)style=”width: 50%;” 直接、HTMLのコード内に、直接CSSのプロパティを記述するやり方です。HTML5からはCSSフィアル(外部ファイル)を作成し、CSSをまとめて書くやり方が一般的です。ただし、これを行えば、外部ファイルよりも優先してCSSの指示が強く認識されます。 |
3 | 作成者がheadタグ内に記述したCSS | 実際は、CSSの外部ファイルにあるような「3」のようなセレクタの種類がありますが、ほとんどこの形式を使わないと思いますので、省略します。 | head内にstyleタグを設定し、その中にCSSを書きます。すると、CSSファイルよりも優先して読み込まれます。ただし、この書き方は一般的ではありません。このようなこともできる、くらいで理解しておいてください。 |
4 | 作成者のCSSファイル(外部ファイル) | idセレクタ | (例)#hoge この設定は他のセレクタよりも強い優先度を持っています。 |
classセレクタ | (例).hoge{width: 50%;} | ||
擬似クラス | (例).hoge:nth-child(n){color: red;} | ||
擬似要素 | (例).hoge::before{content: “”} | ||
タイプセレクタ | (例)p{width: 50%;}/article{width: 50%;} タイプセレクタとは、div / li / p / a /などのタグを指します。 | ||
全称セレクタ | *{font-size: 16px;} 「*(アスタリスク)」は、「すべての種類の要素」を意味し、これを設定することで全てに指示が適用されます。 | ||
5 | ブラウザのデフォルトCSS | – | これは、ブラウザごとに設定されているCSS指定です。何も設定していなくてもmarginやhタグの文字の大きさが設定されていることがありますが、これはデフォルトのCSSです。例えば、文字の大きさは、ブラウザごとに異なったりしますが、それはこの影響があるからです。 |
詳細度
詳細度とは?
さて、優先順位に加えて、ここで「詳細度(Specificity)」という考え方を知る必要があります。例えば、実際は、要素を組み合わせてCSSの指示を出すケースは頻繁にあるはずです。その場合に、結局、優先順位はどちらが強いのか、を判断しなければなりません。その際に、優先順位の強さを数値で示してくれるのが詳細度です。
詳細度は CSS 宣言が適用される際の重みであり、一致するセレクターそれぞれの種類の数によって特定されます。複数の宣言が同じ詳細度であれば、 CSS の中で最後に宣言されたものが要素に適用されます。詳細度は同じ要素に対して複数の宣言が行われている場合のみ適用されます。 引用元
詳細度は、CSSで設定されたセレクタの種類や数を総合的に計算し、本やソフトウェアのバージョンのように数値をふったもので、優先度を定量的に判断することができます。
順位 | 種類 | 詳細度数値 |
---|---|---|
1 | !importnatがついたセレクタ | 1.0.0.0.0 |
2 | style属性内のCSS | 0.1.0.0.0 |
3 | idセレクタ | 0.0.1.0.0 |
4 | classセレクタ(.@@@など)/擬似クラス(.@@@:hover/.@@@::nth-child(n)など)/属性セレクタをもつセレクタ(href属性、attr属性など) | 0.0.0.1.0 |
5 | 要素セレクタ(div / p /a / articleなど指定した要素の全てに適用される)/擬似要素(::before/::after/::first-letterなどがついたセレクタ) | 0.0.0.0.1 |
6 | 全称セレクタ | 0.0.0.0.0 |
詳細度の計算
①「.side_nav h2」というセレクタがあったとします。これは、クラスセレクタと要素セレクタを組み合わせたセレクタです。
セレクタ名 | 詳細度 | 個数 | 結果 |
---|---|---|---|
クラスセレクタ | 0.0.0.1.0 | 1つ | 0.0.0.1.0 |
要素セレクタ | 0.0.0.0.1 | 1つ | 0.0.0.0.1 |
結果、このセレクタの詳細度は、「0.0.0.1.1」となります。
②「#header #global_nav > ul > li.menu-itemt.current-menu-item > a」というセレクタがあったとします。これは幾つもの要素が組み合わされています。
セレクタ名 | 詳細度 | 個数 | 結果 |
---|---|---|---|
idセレクタ | 0.0.1.0.0 | 2つ | 0.0.2.0.0 |
クラスセレクタ | 0.0.0.1.0 | 2つ | 0.0.0.2.0 |
要素セレクタ | 0.0.0.0.1 | 3つ | 0.0.0.0.3 |
結果は、「0.0.2.2.3」となります。
①と②を比較した時に、もちろん、優先順位が高いのが②です。バージョンの最新のように考えて貰えば大丈夫です。
これは非常に計算が簡単ですが、このように簡単なセレクタだけではありません。次のようなコードを目にしたことはないでしょうか? 最初の印象として、セレクタの長さが非常に長い、ということです。「id」や「class」を何度もつなげています。
このような際に役立つのがSpecificity Calculatorです。セレクタをスペースに入力するだけで、数値を出してくれます。
セレクタを詳細に書けば書くほど、詳細度が上がるため優先順位は上がります。ただし、ここにも注意点があります。
①詳細の程度は程々が良い。
少し曖昧な表現ですが、あまり長くならないほうが後々変更がしやすいということです。
②詳細度が同じであれば、書いた順番で決まる
つまり、ブラウザは上から下へ読んでいく動きをしますので、下に置かれている指示が効くということになります。
③「!important」がついているセレクタ同士の比較では、詳細度の数値が高いほうが優先される。
「!important」を多用すると、「!important」がついたセレクタ同士の比較が始まります。その場合は、詳細度の数値で決まります。
まとめ
では、これまでお伝えしてきたことをまとめます。
- 「!important」は全ての優先順位を超えて、非常に強い指示を出すことができる。
- 「!important」の使用は、最後の手段であり、CSSが効かない場合は、優先順位を検討する。
- 優先順位を検討する際は、詳細度の計算が役立ち、それぞのセレクタごとに数値が割り当てられている。
- 数値の解釈は、「バージョン」と捉えて、バージョンが新しいものが数値が高くなり、詳細度が高いことを意味する。