アカベコマイリ

HEAR NOTHING SEE NOTHING SAY NOTHING

CSS で子要素へのスタイル継承を制御する

September 04, 2019開発CSS

ゆうべ Twitter で CSS の暗黙的なスタイル継承の問題点をつぶやいてたら、そのリプで all: initial を教えていただいた。

個々のプロパティーに対する inheritunset は知っていたけれど、すべてを表す all にまとめられるのは初耳。

上記を見るに IE/Edge を除く主要 Web ブラウザーなら利用可能なようだ。IE/Edge でも利用したい場合は Polyfill もある。

ただし all.css を読むと各種プロパティーの標準設定を網羅したクラスを定義、それを包含させたり差分で上書きすることで実現している。そのため CSS の肥大化や差分管理の失敗による事故が怖い。プロパティーの網羅性が継続的に維持されるかという心配もある。よって IE/Edge を諦められことを前提に使用するのが安全だろう。

私としては IE は既に過去の資産を動かすためのもので後継の Edge は独自エンジンをやめて Chromium へ移行するのだから、よほど強く求められない限り対応しないつもりだ。というわけで、これらを除外して all プロパティーによる CSS 継承の制御を試す。

動作確認する。以下のように HTML 要素を階層化させ、

<div class="parent">
  <div class="child1">Child 1</div>
  <div class="child2">Child 2</div>
  <div class="child3">Child 3</div>
</div>

設定による差を見るための CSS を定義。

.parent {
  font-weight: bold;
  color: #e74c3c;
}

.child1 {
  all: initial;
}

.child2 {
  color: initial;
}

.child3 {
  all: initial;
  color: inherit;
}

実際に表示してみると child1 〜 3 はそれぞれ

  1. 全継承が拒否され、標準スタイル
  2. color 継承が拒否され、太字になる
  3. 全継承を拒否した後に color だけ継承、色が変わる

となった。BEM、CSS Modules、CSS in JS などで要素間のスタイル衝突を避けるなら、あわせて all: initial も意識しておくのがよさそうだ。関連する話として以前、

という記事に対して

とコメントしたのだが、

祖先側が子孫側のスタイルを上書きしている箇所が多々あった

については CSS Modules や styled-components だと対策として不十分である。これらでコンポーネント単位にスタイル適用できたとしても、その子への暗黙的な継承は防げない。

そのため根本対策するなら all: initial などを設定して明示的に継承を制御する必要がある。これは !important 地獄を回避するためにも役立つだろう。