CSSの変数(カスタムプロパティ)が期待通りに動作しないときの解決方法
Post on:2021年9月2日
CSSの変数(カスタムプロパティ)は、IEを除くすべてのブラウザでサポートされており、実際のプロジェクトで使用している人も増えてきたと思います。
CSSの変数は非常に便利で使いやすいのですが、期待通りに動作しないときの解決方法を紹介します。
The Big Gotcha With Custom Properties
by Chris Coyier
CSSの変数(カスタムプロパティ)の基礎知識、便利な使い方は以前の記事をご覧ください。
下記は各ポイントを意訳したものです。
※当ブログでの翻訳記事は、元サイト様にライセンスを得て翻訳しています。
- CSSの変数(カスタムプロパティ)が期待通りに動作しない!
- 解決方法 1: 変数を使用する場所にスコープを設定する
- 解決方法 2: 変数を設定するセレクタをカンマ区切りにする
- 解決方法 3: ブランケットモード
- 解決方法 4: 新しいデフォルトのプロパティとフォールバックの導入
- 終わりに
CSSの変数(カスタムプロパティ)が期待通りに動作しない!
最近、私を含めて多くの人がCSSの変数(カスタムプロパティ)が期待通りに動作しないで混乱しているのを目の当たりにしたので、ここに書き留めておきます。
まずは、CSSの変数を定義します。
1 2 3 4 |
html { --color-1: red; --color-2: blue; } |
これら2つの変数を背景のグラデーションに使用します。
1 2 3 4 5 6 |
html { --color-1: red; --color-2: blue; --bg: linear-gradient(to right, var(--color-1), var(--color-2)); } |
ページ上には、いくつかのdivがあるとします。
1 2 |
<div></div> <div class="variation"></div> |
divに背景のグラデーションを適用してみましょう。
1 2 3 |
div { background: var(--bg); } |
もちろん、これは完全に機能します!
では、せっかく変数を使用しているので、バリエーションを作成してみましょう。レッドからブルーではなく、グリーンからブルーにしてみます。つまり、redをgreenにアップデートします。
1 2 3 4 5 6 7 8 9 10 11 12 |
html { --color-1: red; --color-2: blue; --bg: linear-gradient(to right, var(--color-1), var(--color-2)); } div { background: var(--bg); } .variation { --color-1: green; } |
うまくいきません!
サイレンが鳴り響き、クラクションが鳴り響き、家畜が身を隠します。
この実装は、期待通りに動作しません。
私が理解している限りでは、問題は--bgがどちらのdivにも宣言されていないことです。より上位で宣言されていたので、--bgを使用することはできましたが、そこで使用されるまでにその値はロックされます。宣言された時点で--bgがたまたま使用していた他のプロパティを変更したからといって、そのプロパティが使用された場所を探しにいき、依存関係として使用されたすべてのものをアップデートすることにはなりません。
この説明ではピンとこないかもしれません。しかし、これが私が得た精一杯の答えです。
解決策ですか?
いくつかあります。
解決方法 1: 変数を使用する場所にスコープを設定する
このようにすることができます。
1 2 3 4 5 6 7 8 9 10 11 12 |
html { --color-1: red; --color-2: blue; } div { --bg: linear-gradient(to right, var(--color-1), var(--color-2)); background: var(--bg); } .variant { --color-1: green; } |
--bgが両方のdivで宣言されているので、--color-1の依存関係への変更は機能します。
解決方法 2: 変数を設定するセレクタをカンマ区切りにする
一般的に変数は:rootで定義されます。しかし、その場合今回のような問題が発生します。変数を宣言する時に適用するセレクタを追加するだけで、正しいスコープに入るようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
html, div { --color-1: red; --color-2: blue; --bg: linear-gradient(to right, var(--color-1), var(--color-2)); } div { background: var(--bg); } .variation { --color-1: green; } |
他の例を挙げると、下記のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
:root, .button, .whatever-it-is-a-bandaid { --padding-inline: 1rem; --padding-block: 1rem; --padding: var(--padding-block) var(--padding-inline); } .button { padding: var(--padding); } .button.less-wide { --padding-inline: 0.5rem; } |
解決方法 3: ブランケットモード
この方法は、変数をどこにでも入れることができます。
1 2 3 4 5 6 7 |
* { --access: me; --whereever: you; --want: to; --hogwild: var(--access) var(--whereever); } |
ただし、これは良い解決策ではありません。
私は最近、中規模サイトで500msのレンダリング遅延が発生したのを見かけました。これはページの描画ごとにすべてのプロパティを計算する必要があるからです。
期待通りに機能はしますが、セレクタが原因でパフォーマンス上の問題を引き起こす可能性がある稀なケースの一つです。
解決方法 4: 新しいデフォルトのプロパティとフォールバックの導入
この問題を最初に目にしたのは、Stephen Shawの功績のおかげです。
この問題の最初のCSSに戻りましょう。
1 2 3 4 5 6 |
html { --color-1: red; --color-2: blue; --bg: linear-gradient(to right, var(--color-1), var(--color-2)); } |
やりたいことは、2つです。
- 背景全体を上書きする方法
- グラデーションの背景の一部を上書きする方法
そのためには、下記のような方法があります。
1 2 3 4 5 6 7 8 |
html { --color-1: red; --color-2: blue; } div { --bg-default: linear-gradient(to right, var(--color-1), var(--color-2)); background: var(--bg, var(--bg-default)); } |
--bgを全く宣言していないことに注目してください。ただそこに座って値を待っているだけで、もし値が得られれば、それが「勝利」の値となります。しかし、値がなければ--bg-defaultに戻ります(フォールバックとして)。
- --color-1または--color-2を定義すると、期待通りにグラデーションのその部分が置き換えられます(divの1つに触れるセレクタでそれを行う限り)。
- また、--bgを定義して、背景全体を好きなものにリセットすることもできます。
これが最適な方法だと思います。
See the Pen
Variable Play by Chris Coyier (@chriscoyier)
on CodePen.
終わりに
CSSの変数(カスタムプロパティ)には、バグが実際にあります。これはそれらの一つではありません。バグのように感じられますが、どうやらそうではないようです。ただ、知っておかなければならないことの一つです。
sponsors