このレッスンでの目的は、CSS を HTML に適用する方法と競合した場合の解決方法について、もっとも基本的な概念(カスケード・詳細度・継承)の理解を深めていくことです。
このレッスンは他の記事よりも収穫が少なく座学っぽく感じるかもしれませんが、本記事の内容を理解しておくことで今後に役立ちます。このセクションを注意深く読み、次に進む前に概念をよく理解することをお勧めします。
前提条件: | 基本的なコンピューターリテラシー、基本的なソフトウェアがインストールされていること、ファイルの扱い、HTML の基本(HTML 入門)および CSS に関するアイデア(CSS の第一歩)に関する基本的な知識を得ている。 |
---|---|
目的: | カスケードと詳細度、および CSS の継承の仕組みについて学ぶ。 |
競合するルール
CSS は Cascading Style Sheets の略で、最初の単語であるカスケード (cascading) を理解することは非常に重要です。カスケードのふるまいは、CSS を理解するための鍵となりえます。
プロジェクトに取り組んでいるとき、要素に適用されているはずの CSS が機能していないと感じることがあります。それは大抵の場合、同じ要素に適用される可能性のある 2 つ のルールを作ってしまったことに由来します。カスケードおよび、それと密接に関連する詳細度の概念は、そのような競合が存在する際のメカニズムです。実際に要素をスタイリングしているルールがどれなのかは期待と異なる場合があるため、このメカニズムを理解しておく必要があります。
このほかに重要なのは継承という概念です。一部の CSS プロパティは親要素の値をデフォルトで継承し、一方で継承しないものもあります。これにより、予期しない動作が発生する可能性もあります。
まず重要なものを簡単に見てみましょう。それぞれ順に追っていって CSS でどのように相互作用するかを見ていきます。これらはトリッキーな概念のように見えるかもしれませんが、CSSを書く練習を積んでいくと、その動作は明らかになってくるでしょう。
カスケード
スタイルシートのカスケードについて、とてもシンプルに考えるなら CSS ルールの順序が重要であることを意味します。等しい詳細度を持つ 2 つ のルールが適用される場合、CSS の最後に来るものが使用されます。
以下の例では、 h1
に対して 2 つ のルールがあります。この h1
は最終的に青色になります。これらのルールは個別のセレクターを持つため同じ詳細度であるので、ソースで最後にきている方が採用されています。
詳細度
詳細度とは、複数のルールに異なるセレクターがある場合にブラウザーがどのルールを適用するかを決定する方法ですが、同じ要素に適用することもできます。基本的に、セレクターの選択がどの程度具体的になるかの尺度です。
- 要素セレクターはそれほど具体的ではありません。ページに表示されるそのタイプのすべての要素を選択するため、スコアが低くなります。
- クラスセレクターはより具体的です。ページ上の特定の
class
属性値を持つ要素のみを選択するため、スコアはより高くなります。
例を見てみましょう。以下に h1
に適用できる 2 つ のルールを再度示します。この h1
は最終的には赤色になります。クラスセレクターはルールにより高い詳細度を与えるため、要素セレクターを使用したルールがソースの順序でさらに下の方にあっても適用されます。
詳細度スコアリングなどについては、あとで説明します。
継承
ここでは継承についても理解する必要があります。親要素に設定された CSS プロパティ値には、子要素に継承されるものとそうでないものがあります。
例えば、要素に color
と font-family
を設定すると、異なる色とフォントの値を直接適用しない限り、その中のすべての要素もその色とフォントでスタイルされます。
いくつかのプロパティは継承されません。例えば、要素に width
50% と設定した場合、すべての子孫要素は親の幅の 50% の幅を取得しません。もしそんなことになるのら CSS を使うととてもイライラするでしょう。
注: MDN の CSS プロパティリファレンスページには、仕様書セクションの下部に技術情報ボックスがあるのが通例です。このボックスには、そのプロパティに関する多数のデータポイント(継承されているかどうかなど)が一覧表示されます。例として color プロパティの仕様書セクション を参照してください。
これらの概念がどう連携するか理解する
これら 3 つ の概念は、どの CSS をどの要素に適用するかを一緒に制御します。以下のセクションでは、それらがどのように連携するかを見ていきます。少し複雑に見えることもありますが、CSS を使いこなせば覚えやすくなり、忘れた場合はいつでも調べることができます。経験豊富な開発者でさえ、すべてを詳しく覚えているわけではありません。
継承を理解する
継承から始めます。次の例では <ul>
があり、内部にさらに 2 つ のレベルの順序なしリストがネストされています。外側の <ul>
に境界線、パディング、および文字色が指定されています。
文字色については直接の子だけでなく、間接の子にも適用されています。つまり直接の子である <li>
、それに最初のネストされたリスト内のものにも適用されています。そして 2番目 にネストされたリストに special
クラスを追加し、別の色が適用されています。これは子に継承します。
幅(上述したとおり)、マージン、パディング、境界線などは継承されません。境界線がリストの子に継承される場合、すべてのリストとリストアイテムは境界線を表示してしまいます。おそらく、それは欲しい効果ではないはずです。
デフォルトで継承されるプロパティとそうでないものは、主に常識に基づいているのです。
継承の制御
CSS は、継承を制御するための 4 つ の特別なユニバーサルプロパティ値 (universal property values) を提供します。すべての CSS プロパティはこれらの値を受け入れます。
inherit
- 選択した要素に適用されるプロパティ値を、その親要素と同じものに設定します。これは「継承を有効にする」ことを意味します。
initial
- 選択された要素に適用されるプロパティ値を、ブラウザーのデフォルトスタイルシートでその要素に設定されているものと同じ値に設定します。ブラウザーのデフォルトのスタイルシートで値が設定されておらず、かつ、そのプロパティが自然に継承される場合は
inherit
が代わりにプロパティ値として設定されます。 unset
- プロパティを自然な値にリセットします。つまり、プロパティが自然に継承される場合は
inherit
のように動作し、そうでない場合はinitial
のように動作します。
注: 新しい値で revert
もありますが、これはブラウザーのサポートが制限されます。
注: それらの動作の詳細については CSS カスケード入門の CSS 宣言のオリジンを参照してください。
リンクのリストを見て、ユニバーサル値 (universal values) がどのように機能するかを調べることができます。以下のライブサンプルでは、CSS に変更を加えて何が起こるかを確認できます。HTML と CSS を理解するには、実際にコードを試すのが最善の方法です。
以下を試してみてください。
- 2番目 のリストアイテムには、
my-class-1
が適用されています。これは、内部にネストされた<a>
要素に色を継承します。ルールを削除すると、リンクの色はどのように変わるでしょうか? - なぜ 3番目 と 4番目 のリンクがその色であるのか理解できていますか?そうでない場合は、上述しているそれぞれの値の説明を確認してください。
- 例えば
a { color: red; }
というように<a>
要素に新しい色を定義すると、どのリンクの色が変わるでしょうか?
すべてのプロパティ値のリセット
CSS の一括指定プロパティ all
を使用して、これらの継承値の 1 つ を(ほぼ)すべてのプロパティに一度に適用できます。その値として、いずれかの継承値 (inherit
、initial
、unset
、または revert
) を指定できます。新しく変更を開始する際、既知の開始点に戻ることができるように、変更されたスタイルを元に戻す便利な方法です。
以下の例では 2 つ のブロック引用要素 (blockquote) があります。最初のスタイルは blockquote 要素自体に適用され、2 つ目には all
に unset
をセットするようにblockquote に適用されるクラスがあります。
all
の値を他の有効な値に設定してみて、違いを観察してみてください。
カスケードを理解する
HTML 構造に深くネストされた段落が body の CSS と同じ色である理由がわかりました。また導入レッスンではドキュメントの任意の時点で CSS を変更する方法がわかりました(CSS を要素自体に割り当てたり、クラスを作成したり)。そしてここからは、スタイルを設定できるものが複数ある場合に、カスケードがどのようにして CSS ルールを適用していくかを見ていきます。
考慮すべき 3 つ の要因がありますが、ここでは重要度の高い順にリストしています。前にあるものは、後のものを無効にします。
- 重要性 (Importance)
- 詳細度 (Specificity)
- ソースオーダー (Source order)
これらを下から順に、ブラウザーがどうやって CSS を適用しているのかを見ていきましょう。
ソースオーダー
カスケードにおいてソースオーダーがどう重要であるかは、すでに見てきました。重みがまったく同じであるルールが複数ある場合、CSS の最後にあるルールが優先されるというものです。後にあるものが前のものに勝ち、要素のスタイルを上書きしていく規則のようなものと考えることができます。
詳細度
ソースオーダーが重要であるということがわかりました。ある時には、より後ろにあるルールが適用されるはずなのに、競合関係にある前方のものの方が適用されるという状況に出会います。それは前方にあるルールの方がより高い詳細度を持っているためです。より具体的であり、要素をスタイリングするべきものとしてブラウザーによって選択されたのです。
このレッスンで前述したように、クラスセレクターは要素セレクターよりも重みがあるため、クラスで定義されたプロパティは、要素指定されたプロパティをオーバーライドします。
ここで特筆すべきは、セレクターとそれによって適用されるルールについて注目しているのですが、上書きされるのはルール全体ではなく同じプロパティのみであるということです。
この振る舞いは CSS での反復を避けるのに役立ちます。一般的な方法としては、要素に基本スタイルを定義したあと、違いがでるようにクラスを作成することです。例えば、次のスタイルシートではレベル 2 見出し (h2) の基本スタイルを定義し、プロパティと値の一部のみを変更するクラスを作成しました。最初に定義された値はすべての見出しに適用され、その後、より具体的な値がクラスありのものに適用されます。
ブラウザーが詳細度を計算する方法を見てみましょう。要素セレクターの詳細度は低く、クラスで上書きできることはすでにわかったはずです。基本的に、セレクターの重みはポイント単位の値で与えられ、これらを合計して特定セレクターの重みが与えられて、他の一致するものと相対して評価することができます。
セレクターが持つ詳細度の量は、4 つ の異なる値(またはコンポーネント)を使用して測定されます。これは、1,000、100、10、1 のそれぞれの位として考えることができます。
- 「1,000」 宣言が
style
属性(別名、インラインスタイル)内にある場合、これがスコアされます。このような宣言にはセレクターがないため、その詳細度は常にシンプルに 1,000 です。 - 「100」 全体のセレクターの内部にある ID セレクターは、これがスコアされます。
- 「10」 全体のセレクターの内部にあるクラスセレクター・属性セレクター・擬似クラスは、これがスコアされます。
- 「1」 全体のセレクターの内部にある要素セレクターまたは疑似要素には、これがスコアされます。
注: ユニバーサルセレクタ (*
)、コンビネータ (+
、>
、~
、' ') 、及び否定擬似クラス(:not
)は詳細度に影響を及ぼしません。
次の表でわかりやすいいくつかの例を示します。これらを試してみて、なぜ詳細度が与えられるのかをしっかり理解してください。セレクターについてはまだ詳しく説明していませんが、MDN の CSS セレクターで詳細を参照することができます。
セレクター | 1,000 | 100 | 10 | 1 | 詳細度の合計 |
---|---|---|---|---|---|
h1 |
0 | 0 | 0 | 1 | 0001 |
h1 + p::first-letter |
0 | 0 | 0 | 3 | 0003 |
li > a[href*="en-US"] > .inline-warning |
0 | 0 | 2 | 2 | 0022 |
#identifier |
0 | 1 | 0 | 0 | 0100 |
セレクターなし、要素の style 属性にルールがある。 |
1 | 0 | 0 | 0 | 1000 |
先に進む前に、実例を見てみましょう。
何が起こっているのでしょうか?まず、この例の最初の 7 つ のルールにのみ関心があり、お気づきのように、各ルールの前に詳細度の値をコメントしてあります。
- 最初の 2 つ のセレクターはリンクの背景色について競合しています。2番目 のセレクターには ID セレクター があるのでそれが優先され青になります。詳細度は 101 対 201 でした。
- 3番目 と 4番目 のセレクターはリンクテキストの色について競合しています。2番目 のセレクターは 1 つ は要素セレクターの代わりにクラスセレクターが使われているため、白が適用されます。詳細度は 104 対 113 でした。
- セレクター 5〜7 は、リンクホバー時の境界線について競合しています。セレクター6 は 5 に対して要素セレクターが 1 つ少ないため、詳細度 23 対 24 で負けています。一方で、セレクター7 は 5 と 6 の両方に勝っています。サブセレクターの数は 5 と同じですが、クラスセレクターの要素が使われているためです。詳細度は 24 対 23 対 33 でした。
注: これは理解しやすくするためのざっくりとした一例に過ぎません。実際には、セレクタータイプごとにはそれぞれレベルの詳細度があり、より低い詳細度レベルのセレクターによって上書きすることはできません。例えば 100万 のクラスセレクターを組み合わせても、1 つ の ID セレクターのルールを上書きすることはできません。
詳細度を評価するためのより正確な方法は、詳細度を高レベルから開始し必要に応じて低レベルにしていくことです。高い方の詳細度のセレクタースコアが同点の場合にのみ、低レベルを評価することになります。同点でない場合、より高い詳細度レベルを上書きできないため、より低い詳細度レベルのセレクターを無視できます。
!important
ここまで見てきた計算を無効にする特別な CSS があります。使用には十分注意してください !important
というものです。これは特定のプロパティと値を最も重要であると指定するもので、カスケードの通常のルールを上書きします。
例を見てみましょう。2 つの段落があり、そのうちの 1 つ には ID がついています。
何が起きているのかを見てみましょう。理解しにくい場合は、いくつかのプロパティを削除しながら、どうなるか見てみてください。
- 3番目のルールでは
color
とpadding
が適用されていますが、background-color
は適用されていないことようです。なぜでしょうか?ソースオーダーの後の方は、普通は前の方のルールをオーバーライドするため、その観点では 3 つ すべてが適用されるはずです。 - とはいえ、クラスセレクターは要素セレクターよりも詳細度が高いため前者のルールが優先されます。
- 両方の要素には
better
というclass
がありますが、2番目 の要素にはwinning
というid
もあります。ID はクラスよりもより高い詳細度があるため(ページ上では ID を持つ要素は一意に 1 つ しか置けないのに対し、同じクラスを持つ多くの要素がありえるため、ID セレクターの方が非常に限定的になります)、2番目の要素には赤い背景色と 1 ピクセルの黒い境界線が適用され、最初の要素についてはクラスで指定されたように灰色の背景色となり、境界線は消えます。 - 2番目 の要素は赤い背景が適用されていますが、あるはずの境界線はありません。なぜでしょうか? 2番目 のルールでは
border: none
のあとに!important
と宣言されており、高い詳細度であるはずの ID よりも重要なものとして扱われているためです。
注: この !important
宣言をオーバーライドする唯一の方法は、ソースオーダーの後半で同じ詳細度を持つように !important
宣言するか、またはより高い詳細度を持つ宣言に含めることです。
!important
を知っていると便利です。他人のコードでも見かけることがあるからです。ただし絶対に必要な場合を除きあまり使用しないことを強くお勧めします。 !important
はカスケードの普通の挙動とは異なってしまうため、特に大きなスタイルシートで CSS に関わるデバッグが非常に困難になるためです。
使用しなければならない状況の 1 つ としては、コアにある CSS モジュールを編集できない CMS で作業している等で、他の方法では難しい場合にスタイルを実際にオーバーライドしたい場合等があります。でも本当に、回避できる場合は使用しないでください。
CSS ロケーションの効果
最後に、CSS 宣言の重要性は指定されたスタイルシートに依存することにも注意してください。ユーザーは、カスタムスタイルシートを設定して、開発者のスタイルをオーバーライドできます。例えば、視覚障害を持っているユーザーが閲覧するすべてのウェブページのフォントサイズを通常の 2倍 に設定して読みやすくするといったこともあります。
要約
競合する宣言は次の順序で適用され、後の方がそれより前のものを上書きします。
- ユーザーエージェントのスタイルシートの宣言。例えば、他のスタイルが設定されていない場合に使用されるブラウザー標準のスタイルなど。
- ユーザースタイルシートの通常の宣言 (ユーザーが設定したカスタムスタイル)
- 作者のスタイルシートでの通常の宣言 (私たちウェブ開発者によって設定されたスタイルのことです)
- 作者のスタイルシートの重要 (important) な宣言
- ユーザーのスタイルシートの重要 (important) な宣言
ウェブ開発者のスタイルシートがユーザーのそれを上書きするのは理にかなっているので設計を意図どおりに保つことができますが、前述したとおり、ユーザーがウェブ開発者スタイルをオーバーライドする正当な理由がある場合もあります。それは !important
ルールを使用することで実現できます。
スキルをテストしよう!
この記事で多くを網羅しましたが、最も重要な情報を覚えていますか?次に移る前に、この情報を保持しているかを検証するテストがあります — Test your skills: the Cascadeを見てください。
次のステップ
この記事の大部分を理解したのなら、よいでしょう。CSS の基本的な仕組みに慣れてきたということです。次に、セレクターについて詳しく見ていきます。
カスケード・詳細度・継承を完全に理解していなくても心配する必要はありません。このコースでこれまで取り上げてきたなかで、間違いなく最も複雑なことであり、プロのウェブ開発者でさえもたまに扱いにくく感じるものです。このコースを続行していくなかで、この記事にときどき戻り、それについて考え続けることをお勧めします。
スタイルが期待どおりに適用されないという奇妙な問題に出くわした場合は、この記事を参照してください。詳細度の問題である可能性があります。