カスケードと継承

This translation is in progress.

このレッスンでの目的は、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 を理解するには、実際にコードを試すのが最善の方法です。

以下を試してみてください。

  1. 2番目 のリストアイテムには、my-class-1 が適用されています。これは、内部にネストされた <a> 要素に色を継承します。ルールを削除すると、リンクの色はどのように変わるでしょうか?
  2. なぜ 3番目 と 4番目 のリンクがその色であるのか理解できていますか?そうでない場合は、上述しているそれぞれの値の説明を確認してください。
  3. 例えば a { color: red; } というように <a> 要素に新しい色を定義すると、どのリンクの色が変わるでしょうか?

すべてのプロパティ値のリセット

CSS の一括指定プロパティ all を使用して、これらの継承値の 1つ を(ほぼ)すべてのプロパティに一度に適用できます。その値として、いずれかの継承値 (inheritinitialunset、または revert) を指定できます。新しく変更を開始する際、既知の開始点に戻ることができるように、変更されたスタイルを元に戻す便利な方法です。

以下の例では 2つ のブロック引用要素 (blockquote) があります。最初のスタイルは blockquote 要素自体に適用され、2つ目 は all に unset をセットしています。

all の値を他の有効な値に設定してみて、違いを観察してみてください。

カスケードを理解する

HTML 構造に深くネストされた段落が body の CSS と同じ色である理由がわかりました。また導入レッスンではドキュメントの任意の時点で CSS を変更する方法がわかりました(CSS を要素自体に割り当てたり、クラスを作成したり)。そしてここからは、複数の方法でスタイルを設定できる場合に、カスケードがどのようにして CSS ルールを適用していくかを見ていきます。

考慮すべき 3つ の要因がありますが、ここでは重要度の高い順にリストしています。前にあるものは、後のものを無効にします。

  1. 重要性 (Importance)
  2. 詳細度 (Specificity)
  3. ソースオーダー (Source order)

これらを下から順に、ブラウザがどうやって CSS を適用しているのかを見ていきましょう。

ソースオーダー

カスケードにおいてソースオーダーがどう重要であるかは、すでに見てきました。重みがまったく同じであるルールが複数ある場合、CSS の最後にあるルールが優先されるというものです。後にあるものが前のものに勝ち、要素のスタイルを上書きしていく規則のようなものと考えることができます。

詳細度

ソースオーダーが重要であるということがわかりました。ある時には、より後ろにあるルールが適用されるはずなのに、競合関係にある前方のものの方が適用されるという状況に出会います。それは前方にあるルールの方がより高い詳細度を持っているためです。より具体的であり、要素をスタイリングするべきものとしてブラウザによって選択されたのです。

このレッスンで前述したように、クラスセレクターは要素セレクターよりも重みがあるため、クラスで定義されたプロパティは、要素指定されたプロパティをオーバーライドします。

ここで特筆すべきは、セレクターとそれによって適用されるルールについて注目しているのですが、上書きされるのはルール全体ではなく同じプロパティのみであるということです。

この振る舞いは CSS での反復を避けるのに役立ちます。一般的な方法としては、要素に基本スタイルを定義したあと、違いがでるようにクラスを作成することです。例えば、次のスタイルシートではレベル2見出し (h2) の基本スタイルを定義し、プロパティと値の一部のみを変更するクラスを作成しました。最初に定義された値はすべての見出しに適用され、その後、より具体的な値がクラスありのものに適用されます。

ブラウザーが詳細度を計算する方法を見てみましょう。要素セレクターの詳細度は低く、クラスで上書きできることはすでにわかったはずです。基本的に、セレクターの重みはポイント単位の値で与えられ、これらを合計して他の一致と相対して評価することができます。

セレクターが持つ詳細度の量は、4つ の異なる値(またはコンポーネント)を使用して測定されます。これは、1,000、100、10、1 のそれぞれの位として考えることができます。

  1. 「1,000」 宣言が style 属性(別名、インラインスタイル)内にある場合、これがスコアされます。このような宣言にはセレクターがないため、その詳細度は常にシンプルに1,000です。
  2. 「100」 ID セレクターは、これがスコアされます。
  3. 「10」 クラスセレクター・属性セレクター・擬似クラスは、これがスコアされます。
  4. 「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がついています。

何が起きているのかを見てみましょう。理解しにくい場合は、いくつかのプロパティを削除しながら、どうなるか見てみてください。

  1. 3番目のルールでは color と padding が適用されていますが、background-color は適用されていないことようですなぜでしょうか?ソースオーダーの後の方は、普通は前の方のルールをオーバーライドするため、その観点では 3つ すべてが適用されるはずです。
  2. とはいえ、クラスセレクターは要素セレクターよりも詳細度が高いため前者のルールが優先されます
  3. 両方の要素には better という class ありますが、2番目 の要素には winning という id もあります。ID はクラスよりもより高い詳細度があるため(ページ上では ID を持つ要素は一意に 1つ しか置けないのに対し、同じクラスを持つ多くの要素がありえるため、 IDセレクター の方が非常に限定的になります)、2番目 の要素には赤い背景色と1ピクセルの黒い境界線が適用され、最初の要素については灰色の背景色となり、クラスで指定された境界線は消えます。
  4. 2番目 の要素は赤い背景が適用されていますが、あるはずの境界線はありませんなぜでしょうか? 2番目 のルールでは border: none のあとに !important と宣言されており、高い詳細度であるはずの ID よりも重要なものとして扱われているためです。

: この !important 宣言をオーバーライドする唯一の方法は、ソースオーダーの後半で同じ詳細度を持つように !important 宣言するか、またはより高い詳細度を持つ宣言に含めることです。

!important を知っていると便利です。他人のコードでも見かけることがあるからです。ただし絶対に必要な場合を除きあまり使用しないことを強くお勧めします。 !important はカスケードの普通の挙動とは異なってしまうため、特に大きなスタイルシートで CSS に関わるデバッグが非常に困難になるためです。

使用しなければならない状況の 1つ としては、コアにある CSS モジュールを編集できない CMS で作業している等で、他の方法では難しい場合にスタイルを実際にオーバーライドしたい場合等があります。回避できる場合は使用しないでください。

CSS ロケーションの効果

最後に、CSS 宣言の重要性は指定されたスタイルシートに依存することにも注意してください。ユーザーは、カスタムスタイルシートを設定して、開発者のスタイルをオーバーライドできます。例えば、視覚障害を持っているユーザーが閲覧するすべてのウェブページのフォントサイズを通常の 2倍 に設定して読みやすくするといったこともあります。

要約

競合する宣言は次の順序で適用され、後の方がそれより前のものを上書きします。

  1. ユーザーエージェントのスタイルシートの宣言。例えば、他のスタイルが設定されていない場合に使用されるブラウザー標準のスタイルなど。
  2. ユーザースタイルシートの通常の宣言。ユーザーが設定したカスタムスタイル。
  3. 作者のスタイルシートでの通常の宣言。私たちウェブ開発者によって設定されたスタイルのことです。
  4. 作者のスタイルシートの重要 (important) な宣言
  5. ユーザーのスタイルシートの重要 (important) な宣言

ウェブ開発者のスタイルシートがユーザーそれを上書きするのは理にかなっているので設計を意図どおりに保つことができますが、前述したとおり、ユーザーがウェブ開発者スタイルをオーバーライドする正当な理由がある場合もあります。それは !important ルールを使用することで実現できます。

学習: カスケードで遊ぶ

以下のエリア (active learning) で、リンクに適用してある文字色と背景色をオーバーライドするべく 1つ のルールだけ追記してみてください。継承の制御セクションで見た特別な値のうちいずれかを使用して、実際の色の値を使用せず背景色を白に戻す新しいルールで宣言を記述できますか?

もし間違えた場合は、いつでも [reset] ボタンを使用してリセットできます。もし難しい場合は、この解決策を参照してみてください。

次のステップ

この記事の大部分を理解したのなら、よいでしょう。CSS の基本的な仕組みに慣れてきたということです。次に、セレクターについて詳しく見ていきます。

カスケード・詳細度・継承を完全に理解していなくても心配する必要はありません。このコースでこれまで取り上げてきたなかで、間違いなく最も複雑なことであり、プロのウェブ開発者でさえもたまに扱いにくく感じるものです。このコースを続行していくなかで、この記事にときどき戻り、それについて考え続けることをお勧めします。

スタイルが期待どおりに適用されないという奇妙な問題に出くわした場合は、この記事を参照してください。詳細度の問題である可能性があります。

このモジュール

  1. カスケードと継承
  2. CSS セレクター
  3. ボックスモデル
  4. 背景と枠線
  5. テキスト方向の操作
  6. 要素のはみ出し(オーバーフロー)
  7. CSS の値と単位
  8. CSS によるサイズ設定
  9. 画像・メディア・フォーム要素
  10. 表のスタイリング
  11. CSS のデバッグ
  12. CSS の整理