4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Frontend CSS – パート3】なぜ font-family は継承されるのに background は継承されないのか?

4
Posted at

ChatGPT Image Jun 2, 2026, 10_07_17 AM.png

注意
この記事はAIのアシスタントによって翻訳・編集されています。

目次


1. 問題:なぜボタンの文字色がマルーンになるのか?

次のようなコードを考えてみましょう。

<div class="article">
  <p>
    これはテキストです。
    <a class="btn" href="#">登録する</a>
  </p>
</div>
.article {
  color: maroon;
}

.btn {
  background: blue;
  padding: 8px 16px;
  /* color は指定していない */
}

ボタンの文字色は何色になるでしょうか?

答えは マルーン です。.btncolor を指定していないため、親要素 .articlecolor: maroon継承 されるからです。

(補足:上記の例では <button> ではなく <a> タグを使っています。ブラウザのUAスタイルシートがボタンの color を上書きする可能性を避けるためです。あくまで継承の仕組みを説明するためのシンプルな例です。)

🤔 font-familybackground はどちらもCSSプロパティなのに、なぜ一方は自動的に子孫に伝わり、もう一方は伝わらないのでしょうか?

この記事では CSS の継承の仕組みを整理しながら、inheritunsetrevert の違いについて解説します。


2. 本質:CSSにおける継承の仕組み

CSS の各プロパティは、継承プロパティ非継承プロパティのどちらかに分類されます。

なぜ font-family は継承されるのか?

  • font-familyテキストの内容に関わるからです。
  • インターフェースデザインでは、フォントの一貫性が当然求められます。子孫も特に指定がなければ同じフォントを使うべきです。
  • 同じスタイルを繰り返し記述する必要がなくなります。

なぜ background は継承されないのか?

  • background は要素のボックスと表示領域に関わるからです。
  • もし背景が継承されたら、青色の背景を持つセクションの中のすべての子要素も青色の背景を持つことになります。これは不要な繰り返しであり、要素ごとの見た目の区別がつきにくくなります。

よく継承されるプロパティの例:

  • color, font-family, font-size, font-weight, line-height
  • text-align, letter-spacing, word-spacing
  • visibility, white-space, cursor

開発者が「えっ、これも継承されるの?」と驚くプロパティたち:

  • cursor
  • visibility
  • text-transform
  • list-style
  • quotes

例えば:<div class="card">cursor: pointer を設定すると、内部の <span>cursor を再宣言しなくてもポインターになります。cursor は継承プロパティだからです。

継承されない代表的なプロパティ:

  • background, border, margin, padding
  • width, height, box-sizing, display
  • position, top, left, right, bottom

3. 継承を制御する5つのグローバルキーワード

CSSには、継承の仕組みを制御するための5つのグローバルキーワード (CSS-wide keywords) が用意されています。

  • inherit – プロパティが通常継承されるかどうかに関わらず、親から値を強制的に継承します。非継承プロパティを親と揃えたい場合に便利です。
  • initial – プロパティを CSS仕様で定義された初期値 (initial value) に戻します。ブラウザのデフォルトスタイルではありません。例えば display: initialinline になりますが、ブラウザのUAスタイルシートでは divblock になっています。
  • unset – 継承プロパティなら inherit と同じ動作、非継承プロパティなら initial と同じ動作をします。「スマートリセット」 として最も安全な選択肢です。
  • revert – 現在のオリジン (作者スタイルシート) の値を破棄し、カスケードでより低いオリジン (ユーザースタイルシート or UAスタイルシート) の値に戻します。必ずしもUAスタイルシートに戻るとは限りません。
  • revert-layer (Cascade Level 5+、2022年以降サポート) – 同じオリジン内でのみロールバックし、@layer で定義された前のレイヤーの値に戻します。

5つのキーワード比較表

詳細:

キーワード 継承プロパティでの動作 非継承プロパティでの動作 備考
inherit 親から値を継承 親から値を継承 非継承プロパティでも強制的に継承させる
initial 仕様の初期値 仕様の初期値 ブラウザのデフォルトではないことに注意
unset 親から値を継承 仕様の初期値 「スマートリセット」 – 最も安全
revert ユーザー/UAオリジンへ戻す ユーザー/UAオリジンへ戻す 作者スタイルを完全に無視
revert-layer 同じオリジン内の前のレイヤーへ戻す 同じオリジン内の前のレイヤーへ戻す @layer を使っている場合に有効

4. all: 全プロパティを一括リセット(注意点付き)

要素のすべてのプロパティを一度にリセットしたい場合は、all キーワードを使います。値には initial, inherit, unset, revert, revert-layer が指定できます。

.card {
  all: unset;   /* すべてのプロパティを unset のルールに従ってリセット */
  /* その後、必要なスタイルを再定義 */
  display: block;
  padding: 1rem;
  border-radius: 8px;
}

allunicode-bididirectionCSSカスタムプロパティには影響しません。

all: unset は強力ですが、特に buttoninputselecttextarea などのインタラクティブ要素では注意して使う必要があります。リセットによって以下のような重要なデフォルト動作が失われる可能性があります:

  • デフォルトの display 値 (ボタンは本来 inline-block)
  • フォントの継承
  • appearance やブラウザのデフォルトスタイル
  • フォーカススタイルアクセシビリティ関連の動作 (例: フォーカス時のアウトライン)
  • :active:disabled などの状態のデフォルト動作

重要な注意: colorfont-family のような継承プロパティに対して、all: unset はそれらをブラウザのデフォルト値に戻すのではなく、引き続き親から継承します。この点は非常に多くの人が誤解しています。

インタラクティブ要素に all: unset を使う場合は、アクセシビリティに必要なスタイルを必ず復元してください。


5. computed value(計算値) — 継承が実際に行われる場所

「継承とは子要素が親から値をもらうこと」と理解している人は多いですが、実際には computed value(計算値) と呼ばれる中間ステップで発生します。

ブラウザはCSSの値を次のように処理します:

指定値 (specified value) – 宣言された値、または継承された値
       ↓
カスケード値 (cascaded value) – カスケード後
       ↓
計算値 (computed value) – 継承の解決、相対単位→絶対単位への変換など
       ↓
使用値 (used value) – レイアウト後
       ↓
実効値 (actual value) – 丸め、制限など

継承プロパティの場合、ブラウザは親要素の computed value を基にして子要素の値を決定します。 このことを理解しておくと、例えば em がどのように計算されるかといった複雑な動作も把握しやすくなります。


6. emrem – 継承そのものではないが密接に関連する

em は継承とは異なる仕組みですが、親要素の font-size を基準に計算されます。

例:

.parent {
  font-size: 20px;
}

.child {
  font-size: 2em;  /* 親のフォントサイズの2倍 */
}

結果:.childfont-size40px になります。これは継承ではありません(子は 20px を受け取っているわけではないからです)。これは相対値の解決 (relative value resolution) と呼ばれるもので、親の computed value を参照して新しい値を算出しています。

一方、rem はルート要素 (<html>) の font-size を基準にするため、中間の親要素の影響を受けません。

em をネストすると「フォントサイズが倍々になる」問題を避けるためにも、この違いを理解しておくことが重要です。


7. React + TypeScript での実践例

例1: 親から color を継承してしまうボタン

問題: ボタンに color が宣言されていないため、.article から color: maroon を継承してしまう。

// Article.tsx
import React from 'react';
import './Article.css';

export const Article = ({ children }: { children: React.ReactNode }) => {
  return <div className="article">{children}</div>;
};
/* Article.css */
.article {
  color: maroon;
  font-family: Georgia, serif;
}
// LinkButton.tsx (UAスタイルシートの影響を避けるため <a> を使用)
import React from 'react';

interface LinkButtonProps extends React.AnchorHTMLAttributes<HTMLAnchorElement> {
  variant?: 'primary' | 'secondary';
}

export const LinkButton: React.FC<LinkButtonProps> = ({ children, variant = 'primary', className, ...props }) => {
  return (
    <a className={`btn btn-${variant} ${className || ''}`} {...props}>
      {children}
    </a>
  );
};
/* Button.css */
.btn {
  background: #0066cc;
  padding: 8px 16px;
  border-radius: 4px;
  display: inline-block;
  text-decoration: none;
}
.btn-primary {
  /* color なし → 継承される */
}

結果: ボタンの文字色はマルーンになる。

解決策: .btn または .btn-primarycolor を直接宣言する。

.btn {
  color: white;
  background: #0066cc;
  /* ... */
}

「継承された値は、特異度で子要素のセレクタと競合する」と誤解する人が多いですが、実際は違います。子要素に直接宣言された値は、親セレクタの特異度に関係なく、常に継承された値に勝ちます。 子要素にそのプロパティの宣言がまったくない場合にのみ、継承された値が使われます。


例2: unset を使ってコンポーネントのレイアウトをリセット

// Card.tsx
import React from 'react';
import './Card.css';

export const Card: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  return <div className="card">{children}</div>;
};
/* Card.css */
.card {
  all: unset;           /* すべてのプロパティを unset のルールでリセット */
  display: block;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  padding: 16px;
}

例3: all: unset – インタラクティブ要素では注意

ボタンをグローバルCSSの影響から完全に切り離したい場合、all: unset が使えますが、必要なスタイルは必ず復元しなければなりません。

// ResetButton.tsx
import React from 'react';
import './ResetButton.css';

export const ResetButton: React.FC<{ onClick: () => void; children: React.ReactNode }> = ({ onClick, children }) => {
  return (
    <button className="reset-btn" onClick={onClick}>
      {children}
    </button>
  );
};
/* ResetButton.css */
.reset-btn {
  all: unset;
  /* 必須:デフォルトの動作を復元 */
  display: inline-block;   /* ボタンのデフォルトは inline-block */
  cursor: pointer;
  background: #0066cc;
  color: white;
  padding: 8px 16px;
  border-radius: 4px;
}

.reset-btn:focus-visible {
  outline: 2px solid #0066cc;
  outline-offset: 2px;
}

.reset-btn:active {
  transform: scale(0.98);
}

8. CSS変数 – 継承される?されない?

CSS変数 (カスタムプロパティ) は通常のCSSプロパティとは異なり、デフォルトで継承されます

:root {
  --primary-color: #3498db;
}

.card {
  --primary-color: #e74c3c;  /* このコンポーネント内で上書き */
}

button {
  background: var(--primary-color); /* 最も近いスコープの値が使われる */
}

ただし、@property を使うと継承の有無を制御できます。

@property --primary-color {
  syntax: '<color>';
  inherits: false;  /* 継承させない */
  initial-value: #3498db;
}

9. パフォーマンスと継承

「継承はブラウザを遅くする」という誤解がたまにあります。実際には、継承は computed value の段階で処理されるため、レイアウトやペイントの前に完了します。パフォーマンスへの影響はごくわずかです。

実際にパフォーマンスへ影響しやすいのは次のような処理です。

  • リフロー (reflow) – レイアウト変更 (width, height, margin, padding など)
  • リペイント (repaint) – 見た目の変更 (color, background, box-shadow など)
  • セレクタマッチング – 複雑すぎるセレクタ

継承は記述するCSSの量を減らし、通常はパフォーマンスに悪影響を及ぼしません。

たとえプロパティが何段階もの親から継承されていても、ブラウザはレンダリングのたびにDOMツリーを遡って値を探すようなことはしません。継承された値は内部データ構造に保持され、効率的に伝達されます。


10. 実践チェックリスト

  • □ そのプロパティが継承対象か確認したか
  • □ スタイルリセットには initial ではなく unset を使っているか
  • □ 継承を上書きするために !important を濫用していないか(直接宣言で十分)
  • □ CSS変数の継承を理解し、テーマシステムに活用しているか
  • all: unset を使う場合、アクセシビリティとデフォルト動作を復元しているか
  • □ DevTools で computed styles を確認し、継承の問題をデバッグしたか
  • initial はブラウザデフォルトではなく仕様上の初期値であることを理解しているか
  • revert は必ずしもUAスタイルシートに戻るわけではない(ユーザースタイルシートの可能性もある)
  • emrem の違い、特に継承・相対値解決との関係を理解しているか

11. まとめ

  • すべてのCSSプロパティは「継承プロパティ」か「非継承プロパティ」のいずれかです。
  • テキスト関連のプロパティ (typography, color など) は通常継承されます – コードを簡潔で一貫性のあるものにします。
  • レイアウトやボックスモデルに関わるプロパティは通常継承されません – 意図しないスタイルの伝播を防ぎます。
  • 5つのグローバルキーワード (inherit, initial, unset, revert, revert-layer) を使いこなすことで継承を自在に制御できます。
  • unset は「スマートリセット」として最も安全な選択肢です。
  • all を使うと全プロパティを一度にリセットできますが、インタラクティブ要素では特に注意が必要です。
  • CSS変数はデフォルトで継承されますが、@property で制御できます。
  • 継承の実際の処理は computed value の段階で行われます。
  • em は継承そのものではなく「相対値解決」ですが、継承と一緒に語られることが多い重要な概念です。

12. 参考資料


次回予告

👉 【Frontend CSS – パート4】なぜ width: 100% なのにはみ出るのか?Box Model と box-sizing を理解する

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?