継承

CSS ポッドキャスト - 005: 継承

要素をボタンのように見せるための CSS を記述したとします。

<a href="http://example.com" class="my-button">I am a button link</a>
.my-button {
  display: inline-block;
  padding: 1rem 2rem;
  text-decoration: none;
  background: pink;
  font: inherit;
  text-align: center;
}

次に、コンテンツの記事にリンク要素を追加し、class 値を .my-button に設定します。ただし、テキストが期待どおりの色にならないという問題があります。どうしてそうなったのでしょうか?

一部の CSS プロパティは、値を指定しない場合、継承されます。このボタンの場合、この CSS から color継承しています。

article a {
  color: maroon;
}

このレッスンでは、その理由と、継承が CSS の記述を減らすのに役立つ強力な機能である理由について学びます。

継承フロー

継承の仕組みを、次の HTML スニペットを使って見てみましょう。

<html>
  <body>
    <article>
      <p>Lorem ipsum dolor sit amet.</p>
    </article>
  </body>
</html>

ルート要素(<html>)はドキュメント内の最初の要素であるため、何も継承しません。HTML 要素に CSS を追加すると、ドキュメントにカスケード処理が適用されます。

html {
  color: lightslategray;
}

color プロパティは、デフォルトで他の要素によって継承されます。html 要素には color: lightslategray があるため、色を継承できるすべての要素の色は lightslategray になります。

body {
  font-size: 1.2em;
}
p {
  font-style: italic;
}

<p> のみが斜体になります。これは、最も深くネストされた要素であるためです。継承は下位にのみ伝播され、親要素には伝播されません。

デフォルトで継承されるプロパティ

すべての CSS プロパティがデフォルトで継承されるわけではありませんが、多くのプロパティが継承されます。なお、デフォルトで継承されるプロパティのリストは、すべての CSS プロパティの W3 リファレンスから取得したものです。

継承の仕組み

すべての HTML 要素には、デフォルトで初期値が設定されたすべての CSS プロパティがあります。初期値は継承されないプロパティで、カスケードがその要素の値を計算できなかった場合にデフォルトとして表示されます。

継承可能なプロパティは下位にカスケードされます。子要素は、親の値を表す計算値を取得します。つまり、親要素の font-weightbold に設定されている場合、子要素の font-weight が別の値に設定されているか、ユーザー エージェント スタイルシートにその要素の font-weight の値が設定されていない限り、すべての子要素が太字になります。

継承を明示的に継承して制御する方法

継承は要素に予期しない影響を与える可能性があるため、CSS にはその問題に対処するためのツールが用意されています。

inherit キーワード

inherit キーワードを使用すると、任意のプロパティに親の計算値を継承させることができます。このキーワードを使用すると、例外を作成できます。

strong {
  font-weight: 900;
}

この CSS スニペットは、すべての <strong> 要素の font-weight を、font-weight: 700 と同等のデフォルト値 bold ではなく 900 に設定します。

.my-component {
  font-weight: 500;
}

.my-component クラスは、代わりに font-weight500 に設定します。.my-component 内の <strong> 要素も font-weight: 500 にするには、次のように追加します。

.my-component strong {
  font-weight: inherit;
}

これで、.my-component 内の <strong> 要素の font-weight500 になります。

この値は明示的に設定できますが、inherit を使用していて、.my-component の CSS が将来変更された場合、<strong> は自動的に最新の状態に保たれます。

initial キーワード

継承は要素に問題を引き起こす可能性がありますが、initial には強力なリセット オプションが用意されています。

前述のように、CSS ではすべてのプロパティにデフォルト値があります。initial キーワードは、プロパティをその初期のデフォルト値に戻します。

aside strong {
  font-weight: initial;
}

このスニペットは、<aside> 要素内のすべての <strong> 要素から太字を削除し、代わりに初期値である通常の太字にします。

unset キーワード

unset プロパティの動作は、プロパティがデフォルトで継承されるかどうかによって異なります。プロパティがデフォルトで継承されている場合、unset キーワードは inherit と同じになります。プロパティがデフォルトで継承されていない場合、unset キーワードは initial と同じです。

デフォルトで継承される CSS プロパティを覚えておくのは難しい場合があります。そのような場合は unset が役に立ちます。たとえば、color はデフォルトで継承されますが、margin は継承されないため、次のように記述できます。

/* Global color styles for paragraph in authored CSS */
p {
  margin-top: 2em;
  color: goldenrod;
}

/* The p needs to be reset in asides, so you can use unset */
aside p {
  margin: unset;
  color: unset;
}

これで、margin が削除され、color は継承された計算値に戻ります。

unset 値は all プロパティでも使用できます。上の例に戻りましょう。グローバル p スタイルにプロパティが追加された場合、どうなるでしょうか。margincolor に設定されたルールのみが適用されます。

/* Global color styles for paragraph in authored CSS */
p {
    margin-top: 2em;
    color: goldenrod;
    padding: 2em;
    border: 1px solid;
}

/* Not all properties are accounted for anymore */
aside p {
    margin: unset;
    color: unset;
}

aside p ルールを all: unset に変更すると、今後 p に適用されるグローバル スタイルが何であれ、常に設定解除されます。

aside p {
    margin: unset;
    color: unset;
    all: unset;
}

理解度を確認する

継承に関する知識をテストする

デフォルトで継承されるプロパティは次のうちどれですか。

animation
アニメーションは子孫に受け継がれません。
font-size
🎉
color
🎉
text-align
🎉
line-height
🎉

継承するものがない場合、inherit のように動作し、initial のように動作する値はどれですか。

reset
有効な値ではありません。もう一度お試しください。
unset
🎉
superset
有効な値ではありません。もう一度お試しください。

リソース