CSSを指定しているはずなのに、要素にスタイルが当たっていないということがよくありませんか?
タイプミスはしていないし、クラス名の前にピリオド(.)もついていてセレクタの指定も間違っていない…といった場合は、詳細度や継承が原因かもしれません。
この記事では詳細度、継承についてのCSSの動きを解説します。
これらを理解して、よりよいスタイルを記述できるようになりましょう!
カスケード
1つの要素に対して、複数のスタイルが適用されることもあります。
1 2 3 | <h2 class="title">見出しテキスト</h2> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /* ユーザーエージェントスタイルシート */ h2 { display: block; font-size: 1.5em; margin-block-start: 0.83em; margin-block-end: 0.83em; margin-inline-start: 0px; margin-inline-end: 0px; font-weight: bold; } /* 実際に記述しているのはここから */ h1, h2, h3, h4, h5, h6 { margin: 0; padding: 0; font-size: 14px; font-weight: 500; } .title { border-bottom: 4px solid #eaaeb1; font-size: 24px; font-weight: 700; line-height: 1.45; margin: 80px 0 30px; position: relative; padding-bottom: 15px; } |
同じプロパティを重ねて指定している場合は、優先度の高いスタイルが要素に適用されます。
検証ツールで確認すると、指定したプロパティ / 値が画像のように打ち消されていることがあります。
それは別のスタイルに上書きされているのを意味します。
想定通りにスタイルが当たっていないときは、検証ツールで確認してみてください。
スタイル自体が表示されていない場合は、セレクターや値の指定が間違っているかもしれません。
どのスタイルが要素に適用されるのかはカスケード(カスケード処理)によって決められます。
カスケードは以下のように定義されています。
カスケードは、異なるソースから来るプロパティ値を組み合わせる方法を定義するアルゴリズムです。
引用元: CSS カスケード入門 – CSS: カスケーディングスタイルシート | MDN
簡単に言うと、カスケードは定められた優先順位にしたがって要素に適用されるプロパティ/ 値を決定します。
基本的にはソースの順番、一番最後に書かれたスタイルが適用されます。
しかし他の優先順位が関わってくると、話が違います。
次に他の優先順位であるスタイルシートの起源、そして詳細度について説明します。
スタイルシートの起源
サイトを作成するときに、記述したスタイルシートを以下のように読み込みます。
1 2 3 | <link rel="stylesheet" href="/css/style.css"> |
実はサイトが表示されるとき、それ以外のスタイルシートも読み込んでいます。どのスタイルシートのスタイルを適用するかは、カスケードによって決定します。
以下のような起源の異なるスタイルシートが存在します。
ユーザーエージェントスタイルシート
ブラウザが提供しているスタイルシート。デフォルトCSSと呼んだりする。
作成者スタイルシート
サイトのデザインを定義しているスタイルシート。普段さわっているスタイルシートのこと。
ユーザースタイルシート
ユーザーが独自に設定したスタイルシート。
そしてこれらのスタイルシートは、以下の順番で優先されます。
Web制作者からはユーザースタイルシートはどうしようもできないので、気にするのはユーザーエージェントスタイルシートかと思います。
こちらはデフォルトCSSとも呼ばれていて、そちらの方がしっくりくるかもしれません。
サイトを作成するときは、ブラウザ間で表示の差をなくすためにリセットCSSを最初に読み込むことが多いです。
詳細度
詳細度はスタイルが適用される際の重みづけです。セレクターを計算し、より高い詳細度のスタイルを適用します。
詳細度の低いスタイルがそれより後ろに書かれていても、詳細度の高いスタイルが優先されます。
詳細度は高い順で以下のようになります。
レベル | 該当するセレクター |
---|---|
A | IDセレクター 例:#home |
B | クラスセレクター・属性セレクター・擬似クラス 例:.class、[href=”_target”]、:hover |
C | 要素セレクター・擬似要素 例:td、::before |
またインラインスタイル(要素に直接書くCSS 例:<タグ名 style=”プロパティ名: 値;”>)は外部のスタイルシートより優先されるため、これらのセレクターより高い詳細度を持つと言えます。
!important
また、インラインスタイルよりさらに上の優先順位!importantが存在します。
スタイルで!importantはなるべく使わないように、と言われることがあるかもしれません。
!importantはカスケードを破壊し、使用するとその記述を上書きするには以下の方法しかありません。
その記述より後に、同じ詳細度で!importantを指定する
その記述より高い詳細度のセレクターで!importantを指定する
一度!importantを使うとどんどん!importantが多用されていき、詳細度を上げるためにセレクターの指定が複雑になっていきます。
こうなると、どのスタイルが当たっているか把握するのが困難になります。
そのため!importantは慎重に使用してください。
普通にコーディングするとき、使うことは滅多にないと思います。
必要なタイミング、例えばCMSやライブラリなどの記述を上書きする必要がある、などで使用するのが望ましいです。
注意点
詳細度で勘違いしやすい点をいくつか紹介します。
idセレクターとクラスセレクター×11の場合
以下の場合、どちらのスタイルが適用されるでしょうか。
1 2 3 4 5 6 7 8 9 | #id { font-size: 16px; } .class01.class02.class03.class04.class05.class06.class07.class08.class09.class10.class11 { font-size: 18px; } |
よくidセレクターの重みは100、クラスセレクターの重みは10と紹介されます。
それにしたがって計算すると
10 × 11 = 110
クラスセレクターのスタイルが適用されそうです。
ですが、実際にはidセレクターで指定したスタイルが要素に適用されます。
詳細度を計算するとき、先ほど紹介したレベルA、B、Cと言った順番に見ていきます。
Aの個数が同じ場合にBの個数を比較する…といった具合で詳細度は計算されます。
影響を及ぼさないセレクター
ユニバーサルセレクター(*)、結合子(+、>など)と否定擬似クラスは、詳細度の計算に影響しません。
1 2 3 | nav > a:hover::before |
これはレベルAは0、Bは1、Cは3です。
1 2 3 4 5 6 7 8 9 | ul > li { font-size: 18px; } ul li { font-size: 16px; } |
これだと子結合子(>)があるので上の方が優先されそうですが、どちらも詳細度はAは0、Bは1、Cは3です。
同じ詳細度の場合は、一番最後に書かれたスタイルが適用されます。
計算ツール
以下のサイトでセレクタの詳細度を確認できます。
実際にコーディング中に利用することがないかもしれません。
ですが、うまくスタイルが当たらないときなどに使ってみてください。
継承
またスタイルがうまく当たっていないという場合は、継承が原因の可能性もあります。
継承は以下のように定義されています。
継承
CSSにおいて、継承 (inheritance) はある要素のあるプロパティに値が指定されなかった場合の挙動を制御します。
引用元:継承 – CSS: カスケーディングスタイルシート | MDN
簡単にいうと、親のプロパティの値が、子要素に引き継がれて適用されるのが継承になります。
プロパティごとに継承するかどうか定義されています。
いまいちピンと来ないかもしれないので、具体例を挙げて説明します。
たとえばwebサイト全体でのデフォルトの文字の大きさを20pxにしたいとき、すべての要素にfont-size: 20pxを指定したくないですよね?
その場合、このように記述していると思います。
1 2 3 4 5 | html { font-size: 20px; } |
テキストが20pxになり、大きくなっています。ですがタイトルの文字の大きさは変わっていません。
それはタイトルの要素にはフォントサイズが指定されていて、その下のテキストにはフォントサイズが指定されていなかったからです。
1 2 3 4 5 | .card__title { font-size: 16px; } |
このように要素にプロパティが指定されていない場合、親のプロパティの値の影響を受けることが分かります。
普段何気なく指定しているスタイルに継承が関わってきているのですね。
継承の挙動を知っておくことで、余計なスタイルを書くことを避けられます。
継承されるかどうか
プロパティが継承するかどうかの調べ方を紹介します。
まず「調べたいプロパティ名 mdn」で検索します。検索結果にそのプロパティのリファレンスがヒットするので、クリックします。
スクロールして下の方に公式定義という見出しがあります。
継承の項目でありと表示されていれば継承プロパティ、なしと表示されていれば非継承プロパティです。
継承する値
プロパティの数値の指定に、絶対値と相対値があります。
常に一定の値をとる
例:px など
相対値
何かと比較にしてサイズが決まる
例:em、rem、vw、% など
継承する値が絶対値の場合は、その値が継承されます。
相対値の場合は、親要素と子要素の値をかけ合わせた値が継承されます。
相対値の継承について具体例を挙げて説明します。
1 2 3 4 5 6 7 | <body> <p class="txt"> テキストテキストテキストテキストテキストテキスト<span>囲んでいるテキスト</span>テキストテキストテキストテキスト </p> </body> |
1 2 3 4 5 6 7 8 9 10 11 12 13 | body { font-size: 10px; } .txt { font-size: 1.5em; } .txt > span { font-size: 1.2em; } |
pタグのテキストは15pxで、その中のspanタグで囲まれている文字は12pxになる想定です。
しかしブラウザで見てみると、spanタグの方が大きく表示されています。
検証ツールで値を確認してみましょう。
18pxになっています。
なぜそうなっているかというと
10px × 1.8 = 18px
で相対値の継承だと親要素の影響を受けるのですね。
相対値のまま、spanタグの文字が12pxになるように指定する場合は
で想定通りに表示されます。
個人的にはletter-spacingが思った通りの挙動にならないことがたまにあり、疑問に思っていました。
letter-spacingは基本的にemを指定するので、親要素でletter-spacingを指定した場合に影響を受けてしまいます。
文字の大きさと違って気づきにくいので注意ですね。
まとめ
CSSはシンプルな構文で、詳細度や継承を知らなくても特に問題はありません。
ですが何も考えずにCSSを書いていくと、複数人で作業しづらく保守・運用のフェーズになると破綻しがちです。
詳細度や継承の動きを理解していると、よりシンプルで効率的なコードを書くことができます。
具体的なCSSの活用例ではなく座学的な内容になりましたが、CSSに慣れてきたらぜひ押さえておきましょう。