📋

定義されたCSS変数が::backdrop内で参照できない

2023/02/05に公開

モダンブラウザで <dialog> 要素が対応し始めて、モーダルウィンドウを <dialog> 要素を使って実装してみたときに気づいた現象です。

CSS 変数が参照できない?

::backdrop 擬似要素を使って <dialog> が開いたときの背景色を指定してみます。

:root {
  // モーダルウィンドウの背景色を定義
  --bg: rgb(0 0 0 / 15%);
}
dialog::backdrop {
  // モーダルウィンドウが開いたときの背景色に指定
  // 反映されない!?
  background-color: var(--bg);
}

すると、変数 --bg が参照されずに背景色が適用されません。

仕様を見てみる

WHATWG の仕様 を見てみると、次のように書かれています。

It does not inherit from any element and is not inherited from.
どの要素からも継承されず、また継承されることもない。

つまり、::backdrop 内で CSS 変数を参照できないのは仕様ということみたいです。

解決策

継承されないので、:root と ::backdrop の両方で定義しておく必要があります。

:root {
  // グローバル変数用
  --bg: rgb(0 0 0 / 15%);
}
::backdrop {
  // <dialog>変数用
  --bg: rgb(0 0 0 / 15%);
}
dialog::backdrop {
  background-color: var(--bg);
}

ちなみに、次のようにセレクタをまとめて書くとブラウザが ::backdrop 擬似要素に対応していないときに :root で定義された CSS 変数自体も無効となってしまうので分けて書きます。

:root, ::backdrop {
  // まとめて書くのはNG
  --bg: rgb(0 0 0 / 15%);
}
dialog::backdrop {
  background-color: var(--bg);
}

それを防ぐための救世主 :is() セレクタがありますが、これを使うとなぜか ::backdrop 内で CSS 変数が無効となってしまいます。これはバグなのか仕様なのかはわかりません。

:is(:root, ::backdrop) {
  --bg: rgb(0 0 0 / 15%);
}
dialog::backdrop {
  // 効かない
  background-color: var(--bg);
}

なので、今のところは素直に分けて書く以外の方法はなさそうです。

Discussion