前の記事で、様々な CSS のセレクタを学びました。作業のある時点で、複数の CSS 規則が同一の要素に一致するセレクターを持つ状況になる場合があることに気が付くでしょう。そのような場合、どの CSS 規則が「勝利」し、最終的に要素に適用される規則になるのでしょうか?これはカスケードと呼ばれる仕組みで制御されています。これは継承 (要素がプロパティ値を親から受け継ぐことが、他からは受け継がないこと) にも関連します。この記事では、 CSS のカスケードとは何か、厳密度とは何か、重要度とは何か、複数の規則からどのようにプロパティが継承されるかを定義します。

前提知識: 基本的なコンピューターリテラシー, 基本的なソフトウェアのインストール, ファイルでの作業の基本的な知識, HTML の基本 (HTML 入門を学習のこと), CSS の動作に関する概念 (このモジュールの前の記事を学習のこと)。
目的: CSS におけるカスケードと特殊性、継承の動作について学ぶこと。

要素の最終的なスタイルはさまざまな場所で指定でき、複雑な方法で相互作用することがあります。この複雑なインタラクションは CSS を強力にしますが、混乱を招き、デバッグが困難になる可能性もあります。この記事は、その複雑さの一部を解決することを目的としています。すぐに理解できなくても心配しないでください - これは CSS 理論の最も理解しにくい部分の1つです。今それを試してみることをお勧めしますが、それからカスケードと継承についての質問が出たときに戻るための便利なガイドとして近くに保管してください。

カスケード

CSS は Cascading Style Sheets の略語で、カスケードの概念が重要であることを示しています。最も基本的なレベルでは、CSS ルールの順序が重要であることを示していますが、それよりも複雑です。どのセレクタがカスケードで勝つかは、3つの要因に左右されます (これらは、重みの順にリストされています - 初期のものは後のものを無効にします)。

  1. 重要性
  2. 厳密度
  3. ソース順

重要度

CSSには、特定の宣言が常に他の宣言より優先されるようにするために使用できる特別な構文 !important があります。

例を見てみましょう。

<p class="better">This is a paragraph.</p>
<p class="better" id="winning">One selector to rule them all!</p>
#winning {
  background-color: red;
  border: 1px solid black;
}

.better {
  background-color: gray;
  border: none !important;
}

p {
  background-color: blue;
  color: white;
  padding: 5px;
}

これにより、次のようになります。

何が起こっているのかを見ていきましょう。

  1. 3番目のルールの colorpadding の値が適用されていますが、background-color は無効です。どうして? 実際には3つすべてが確実に適用されるべきです。なぜなら、ソース順の後の方の規則が一般に以前の規則を上書きするからです
  2. ただし、ID/クラスセレクタは要素セレクタよりも高い特異性を持つため、上記の規則に勝ちます (これについては次のセクションで詳しく説明します)
  3. どちらの要素も betterclass を持っていますが、2番目の要素は winningid も持っています。ID はクラスよりもさらに高い特異性を持っているので (ページ上の一意の ID ごとに1つの要素しか持てませんが、同じクラスを持つ要素はたくさんあります -  ID セレクタはターゲットの内容に非常に特有です)。クラスで指定されているように、最初の要素が灰色の背景色を取得し、境界線がない状態で、ピクセルの黒い境界線は両方とも2番目の要素に適用する必要があります
  4. 2番目の要素は赤い背景色を取得しますが、境界線は表示しません。なぜでしょう? 2番目のルールでの !important 宣言のために - この後の border: none は、ID の方がより高い特異性を持っていても、この宣言が前のルールの境界値を上回ることを意味します

メモ: この !important 宣言を無効にする唯一の方法は、ソース順の後の方に同じ特定性の別の !important 宣言を含めるか、より高い特異性を持つ宣言を含めることです。

他の人のコードでそれに出くわしたときにそれが何であるかを知るために、 !important の存在を知っておくと便利です。 ただし、絶対に必要な場合以外は、絶対に使用しないことを強くお勧めします。コア CSS モジュールを編集できない CMS で作業していて、他の方法でオーバーライドできないスタイルをオーバーライドしたい場合は、使用する必要があるかもしれません。しかし実際には、避けることができるのであれば、使用しないでください。カスケードの通常の動作方法が !important によって変更されるため、CSS の問題のデバッグが、特に大きなスタイルシートでは困難になります。

CSS 宣言の重要性は、それがどのスタイルシートで指定されているかに依存することにも注意してください。たとえば、ユーザが視覚的に不自由な場合などにカスタムスタイルシートを設定して開発者のスタイルを上書きすることができます。 読みやすくするために、訪問するすべての Web ページのフォントサイズを通常のサイズの2倍にします。

矛盾する宣言は次の順序で適用され、後のものは前のものをオーバーライドします。

  1. ユーザエージェントのスタイルシートの宣言 (他のスタイルが設定されていない場合に使用されるブラウザのデフォルトスタイルなど)
  2. ユーザスタイルシート (ユーザによって設定されたカスタムスタイル) での通常の宣言
  3. 著者のスタイルシートでの通常の宣言 (これらは私たち、Web 開発者によって設定されたスタイルです)
  4. 著者スタイルシートにおける important 宣言
  5. ユーザスタイルシートにおける important 宣言

Web 開発者のスタイルシートがユーザのスタイルシートを上書きすることは理にかなっているので、デザインは意図したとおりに保つことができますが、前述の通りユーザは Web 開発者のスタイルをオーバーライドする正当な理由があります。

厳密度

厳密度は基本的に、セレクタがどの程度具体的であるか、つまり一致できる要素の数を表します。上記の例に示すように、要素セレクタの特異性は低くなります。クラスセレクタはより高い厳密度を持っているので、要素セレクタに勝ちます。ID セレクタはさらに高い特異性を持っているので、クラスセレクタに勝ちます。ID セレクタに勝つための唯一の方法は !important を使用することです。

セレクタの厳密度の量は、4つの異なる値 (または構成要素) を使用して測定されます。これは、数千、数百、数十、および1と考えることができます。

  1. 千: 宣言が style 属性、つまりインラインスタイルと呼ばれる場合は、この列で1つ採点してください。そのような宣言はセレクタを持っていません、そのためそれらの厳密度は常に単純に1000です
  2. 百: 全体のセレクタの内側に含まれている各 ID セレクタについて、この列に1つのスコアを付けます
  3. 十: 全体のセレクタ内に含まれる各クラスセレクタ、属性セレクタ、または擬似クラスについて、この列に1つずつスコアを付けます
  4. 一: 全体のセレクタの内側に含まれる各要素セレクタまたは疑似要素について、この列に1つのスコアを付けます。

メモ: Universal selector (*), combinators (+, >, ~, ' ') and negation pseudo-class (:not) have no effect on specificity.

次の表は気分を引き立たせるためのいくつかの例を示しています。これらを調べて、なぜそれらがその厳密度を持っているのかを確実に理解してください。

セレクタ 総厳密度
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

メモ: 複数のセレクタが同じ重要性と厳密度を持つ場合、どのセレクタが勝つかは Source order の後に来るセレクタによって決まります。

先に進む前に、実際の例を見てみましょう。これは、これから使用する HTML です。

<div id="outer" class="container">
  <div id="inner" class="container">
    <ul>
      <li class="nav"><a href="#">One</a></li>
      <li class="nav"><a href="#">Two</a></li>
    </ul>
  </div>
</div>

そして、これが例の CSS です。

/* specificity: 0101 */
#outer a {
  background-color: red;
}

/* specificity: 0201 */
#outer #inner a {
  background-color: blue;
}

/* specificity: 0104 */
#outer div ul li a {
  color: yellow;
}

/* specificity: 0113 */
#outer div ul .nav a {
  color: white;
}

/* specificity: 0024 */
div div li:nth-child(2) a:hover {
  border: 10px solid black;
}

/* specificity: 0023 */
div li:nth-child(2) a:hover {
  border: 10px dashed black;
}

/* specificity: 0033 */
div div .nav:nth-child(2) a:hover {
  border: 10px double black;
}

a {
  display: inline-block;
  line-height: 40px;
  font-size: 20px;
  text-decoration: none;
  text-align: center;
  width: 200px;
  margin-bottom: 10px;
}

ul {
  padding: 0;
}

li {
  list-style-type: none;
}

このコードから得られる結果は次のとおりです。

だからここで何が起こっているのでしょう? まず最初に、この例の最初の7つの規則にだけ興味があります、そしてあなたが気づくように、それぞれの前のコメントに厳密度の値を含めました。

  • 最初の2つのセレクタは、リンクの背景色のスタイリングをめぐって競合しています。2番目のセレクタは、チェーン内に追加の ID セレクタがあるため、背景色を勝ち取って青にします
  • 3番目と4番目のセレクタは、リンクのテキストカラのスタイル設定をめぐって競合しています。2番目のセレクタが勝ち、テキストを白にします。なぜならそれは1つ少ない要素セレクタを持っていますが、欠けているセレクタは1よりも10の価値があるクラスセレクタと交換されます。だから勝つ厳密度は113対104です
  • セレクタ5〜7は、ホバーしたときにリンクの境界線のスタイリングをめぐって競合しています。セレクタ6は明らかに23対24の厳密度で5つに落ちます - それはチェーン内の1つ少ない要素セレクタを持ちます。ただし、セレクタ7は、5と6の両方に勝っています。チェーン内のサブセレクタの数は5と同じですが、要素がクラスセレクタに置き換えられています。だから勝つ厳密度は33対23と24です。

メモ: まだ示していない場合は、すべてのセレクタをもう一度見直して、示されているように厳密度の値が与えられている理由を理解してください。

ソース上の順序

前述のように、競合する複数のセレクタの重要性と特異性が同じ場合、どの規則に勝つかを決定するのに役立つ3つ目の要因はソース順です。後の規則が前の規則に勝ちます。例えば:

p {
  color: blue;
}

/* This rule will win over the first one */
p {
  color: red;
}

この例では、ソースの順序が厳密度によって却下されるため、最初の規則が優先されます。

/* This rule will win */
.footnote {
  color: blue;
}

p {
  color: red;
}

規則の混合のメモ

このカスケード理論すべて、およびどのスタイルが他のスタイルに適用されるのかを検討するときに留意すべきことの1つは、これらすべてがプロパティレベルで発生することです。プロパティは他のプロパティを上書きしますが、ルール全体が他のルールをオーバーライドしません。複数の CSS ルールが同じ要素に一致する場合、それらはすべてその要素に適用されます。その後になって初めて、それぞれのどのスタイルが他のスタイルよりも勝つかを判断するために、競合するプロパティが評価されます。

例を見てみましょう。まず、いくつかの HTML です:

<p>I'm <strong>important</strong></p>

そして今度はそれをスタイルするための CSS です:

/* specificity: 0002 */
p strong {
  background-color: khaki;
  color: green;
}

/* specificity: 0001 */
strong {
  text-decoration: underline;
  color: red;
}

結果:

この例では、その厳密度により、最初のルールのcolor プロパティが2番目のルールの color プロパティを上書きします。ただし、最初のルールの background-color と2番目の text-decoration の両方が <strong> 要素に適用されます。また、その要素のテキストは太字で表示されています。これはブラウザのデフォルトスタイルシートから来ています。

継承

CSS の継承はすべての情報を取得し、要素に適用されているスタイルを理解するために調査する必要がある最後の部分です。アイデアは、要素に適用されたいくつかのプロパティ値がその要素の子によって継承されること、あるいはそうでないことです。

  • たとえば、font-familycolor を継承するのは理にかなっています。font-family を <html> 要素に適用することで、サイト全体のベースフォントを簡単に設定できます。その後、必要に応じて個々の要素のフォントを上書きできます。 基本フォントをすべての要素で別々に設定しなければならないのは本当に面倒です
  • 別の例として、marginpaddingborderbackground-image が継承されないことは意味があります。コンテナ要素にこれらのプロパティを設定し、それらをすべての子要素すべてに継承させてから、個々の要素ごとにそれらすべての設定を解除する必要があった場合に発生するスタイリング/レイアウトの混乱を想像してください

どのプロパティがデフォルトで継承され、どのプロパティがそうでないかは、常識にほとんど及びません。確実にしたい場合は、CSS リファレンスを参照してください。各プロパティページには、継承されているかどうかなど、その要素に関するさまざまな詳細を含む要約表が含まれています。

継承の制御

CSS は継承を指定するために、四つの特殊なプロパティ値を提供しています。

inherit
選択された要素に適用されたプロパティ値を、親要素のものと同じになるように設定します。
initial
選択された要素に適用されたプロパティ値を、ブラウザーの既定のスタイルシートの値と同じになるように設定します。ブラウザーの既定のスタイルシートで値が設定されておらず、プロパティが自然に継承された場合は、プロパティ値は代わりに inherit に設定されます。
unset
プロパティを自然の値にリセット、つまりプロパティが自然に継承されたものであれば inherit のように動作し、そうでなければ initial のように動作します。
revert
現在のオリジンがスタイルを適用していなかった場合のようにプロパティの値を戻します。つまり、プロパティの値は (設定されている場合は) ユーザースタイルシートの値に設定されるか、そうでなければ、ユーザーエージェントの既定のスタイルシートから取得されます。

それぞれの値や動作の仕組みは、 CSS 宣言のオリジン in CSS カスケード入門を参照してください。

メモ: initial 及び unset は Internet Explorer は対応していません。

この中で、 inherit は頻繁に興味深いものです。 — これは要素に対して、明示的に親からプロパティ値を継承させることができます。

例を見てみましょう。まず、 HTML です。

<ul>
  <li>Default <a href="#">link</a> color</li>
  <li class="my-class-1">Inherit the <a href="#">link</a> color</li>
  <li class="my-class-2">Reset the <a href="#">link</a> color</li>
  <li class="my-class-3">Unset the <a href="#">link</a> color</li>
</ul>

そしてスタイル付けのための CSS です。

body {
  color: green;
}

.my-class-1 a {
  color: inherit;
}

.my-class-2 a {
  color: initial;
}

.my-class-3 a {
  color: unset;
}

結果:

何が起きているのかを説明しましょう。

  • 最初の規則は、<body>color を緑色に設定しています
  • color プロパティが自然に継承されると、本文の全ての子要素が同じ緑色になります。なお、ブラウザはリンクの色を color プロパティの自然な継承ではなく既定の青に設定するので、リスト中の最初のリンクは青になります
  • 二番目の規則は、my-class-1 クラスを持つ要素のリンクを、親から色を継承するように設定します。この場合、リンクは色をその親である <li> から継承し、既定ではそれがさらにそのその親である <ul> から継承し、最終的には <body> から継承するので、 color は最初のルールで設定した green に設定されます
  • 三番目の規則は、my-class-2 クラスを持つ要素内の全てのリンクを選択し、色を initial に設定します。ブラウザによって文字列に設定されている初期値は黒なので、このリンクは黒に設定されます
  • 最後の規則は、my-class-3 クラスを持つ要素内の全てのリンクを選択し、その色を unset に設定します。つまり値の設定を解除します。color プロパティは自然に継承されるプロパティなので、値に inherit の値を設定したように動作します。その結果、このリンクは本文と同じ色 — 緑に設定されます

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

CSS の省略形のプロパティ all を使用すると、これらの継承値の1つを (ほぼ) すべてのプロパティに同時に適用できます。その値は、継承値 (inheritinitialunset、または revert) のいずれかになります。新しい変更を始める前に既知の開始点に戻ることができるように、スタイルに加えられた変更を元に戻す便利な方法です。

アクティブラーニング: カスケードで遊ぶ

このアクティブラーニングでは、デフォルトでリンクに適用されている色と背景色を上書きする単一の新しいルールを作成してみてください。Controlling inheritance セクションで見た特別な値の1つを使って、実際の色の値を使わずに背景色を白にリセットする宣言を新しい規則で書くことができますか?

間違えた場合は、リセットボタンを使用していつでもリセットできます。本当に動かなくなったら、Show solution ボタンを押して答えを確認してください。

次の学習

この記事の大部分を理解していれば、よくできました - あなたは CSS の基本的な仕組みに詳しくなりました。中心理論の最後の部分はボックスモデルです。これについては次に説明します。

カスケード、厳密度、および継承を完全に理解していなくても心配しないでください。これは間違いなくこれまでのところ説明してきた中で最も複雑なことであり、プロの Web 開発者でさえも注意が必要なことです。コースを継続しながらこの記事に何度か戻って、それについて考え続けることをお勧めします。期待通りにスタイルが適用されないという奇妙な問題に遭遇し始めたらここに戻って参照してください。それは厳密度の問題かもしれません。

このモジュール

ドキュメントのタグと貢献者

このページの貢献者: silverskyvicto, mdnwebdocs-bot, mfuji09
最終更新者: silverskyvicto,