CSS で子要素へのスタイル継承を制御する
ゆうべ Twitter で CSS の暗黙的なスタイル継承の問題点をつぶやいてたら、そのリプで all: initial
を教えていただいた。
all: initial でしょうか?
— 全部入りHTML太郎 (@_yuheiy) September 3, 2019
個々のプロパティーに対する inherit
と unset
は知っていたけれど、すべてを表す 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 はそれぞれ
- 全継承が拒否され、標準スタイル
color
継承が拒否され、太字になる- 全継承を拒否した後に
color
だけ継承、色が変わる
となった。BEM、CSS Modules、CSS in JS などで要素間のスタイル衝突を避けるなら、あわせて all: initial
も意識しておくのがよさそうだ。関連する話として以前、
という記事に対して
CSS Modules や styled-components は定義を自動的に一意として定義順の問題を回避するものだから、これで問題が起きるのなら手動命名の BEM はより脆弱なのではなかろうか。 / “CSS Moduleを止めようとしている話(具体的な解決編) - saneyuki_s log” https://t.co/3wY5e4DMHh
— アカベコ (@akabekobeko) March 15, 2019
とコメントしたのだが、
祖先側が子孫側のスタイルを上書きしている箇所が多々あった
については CSS Modules や styled-components だと対策として不十分である。これらでコンポーネント単位にスタイル適用できたとしても、その子への暗黙的な継承は防げない。
そのため根本対策するなら all: initial
などを設定して明示的に継承を制御する必要がある。これは !important
地獄を回避するためにも役立つだろう。