CSSのカスタムプロパティでテーマ切り替えを手軽に実装する
Webサイトのデザインにおいて、ライトモードとダークモードの切り替えはユーザー体験を大きく左右する要素です。従来はJavaScriptでクラスを付与し、CSSを上書きする方法が一般的でしたが、コードが冗長になりがちでした。CSSカスタムプロパティ(CSS変数)を活用すると、少ないコードで洗練されたテーマ管理が可能になります。
東京での制作活動の中で、複数のプロジェクトでテーマ切り替えを実装してきました。共通する課題は、保守性の低下とスタイルの散乱です。:root や html 要素に対してプロパティを定義し、メディアクエリやクラスの付与だけで切り替える仕組みは、規模の大きいプロジェクトほど効力を発揮します。
本記事では、基本的な宣言方法から実装パターン、注意点までを整理しました。日々のWeb制作やアプリ画面の設計で、テーマ切り替えの手間を削減したい方の参考になれば嬉しいです。
カスタムプロパティとは何か
CSSカスタムプロパティとは、--variable-name: value; という形式で定義する再利用可能な値です。var(--variable-name) で呼び出せます。Sassの変数と似ていますが、最大の違いはJavaScriptから値を読み書きできる点と、実行時に値が評価される点です。
たとえば --color-primary: #2563eb; と定義しておけば、ボタン、リンク、見出しなどあらゆる箇所で一貫した色を使えます。値を変更したいときは1行書き換えるだけで済み、修正漏れが起きにくくなります。
テーマ切り替えでよくある課題
従来のテーマ切り替えでは、body.dark .header { ... } のようにテーマごとにセレクタを追加していく手法が主流でした。テーマが3種類、4種類と増えると、CSSファイルの行数は一気に膨らみます。
さらに、保守の段階で「どの色が何に対応しているのか」が追いにくくなる問題もあります。Sassの変数を多用するとビルドが必要で、リアルタイムな確認が難しい場面も出てくるでしょう。CSSカスタムプロパティはこれらの問題を解消する手段として注目されています。
基本的な実装の流れ
まずは:rootに対してベースとなるプロパティを定義します。次に、テーマを切り替えたい要素に対して別の上書きブロックを用意します。prefers-color-scheme を使えば、OS設定に合わせた自動切替も可能です。
実際のコードはシンプルで、HTML側にdata-theme属性を切り替えるボタンを置き、JavaScriptでその属性を更新するだけで動作します。サーバーからテーマを配信する場合も、CSSだけで完結する範囲であればエフェクトのちらつきも抑えられます。
複数テーマを統一的に扱う設計
ライト・ダークだけでなく、ブランド別のカラーリングや、ハイコントラストモードを用意する場合にもカスタムプロパティは有効です。テーマごとのCSSを分けて読み込むのではなく、1つのファイル内で[data-theme="brand-a"]のように属性セレクタを使うと管理が楽になります。
アプリ開発では、Cordova環境での実装経験がきっかけになることもあります。PhoneGapタグの記事のような資料が今でも役立っています。Web技術とネイティブの境界を扱う場面でも、変数設計の考え方は共通しています。
実装方法の比較
テーマ切り替えを実現する方法はいくつかあります。主なアプローチを整理しました。
| 手法 | 実装の手間 | 保守性 | パフォーマンス | JS依存 |
|---|---|---|---|---|
| CSSカスタムプロパティのみ | 低 | 高 | 高 | 不要(自動)/ 最小(手動) |
| Sass変数 + JS制御 | 中 | 中 | 高 | 必要 |
| JSでstyle属性を操作 | 低 | 低 | 中 | 必要 |
| 別CSSファイルを切替 | 中 | 低 | 中 | 必要 |
カスタムプロパティは他の手段と比べてバランスが良く、導入のハードルが低いことが分かります。
アクセシビリティと運用の配慮
テーマ切り替えを実装する際、コントラスト比を意識することが大切です。背景色と文字色の組み合わせがWCAGの基準に沿っているか確認しましょう。CSSカスタムプロパティを使うと、色の値をまとめて管理できるため、検証ツールとの連携もスムーズです。
パフォーマンス面では、カスタムプロパティの変更による再描画コストは比較的小さいとされています。ただし、多数の要素に対して頻繁に値を変更するアニメーションでは、will-change や transform と組み合わせるなどの工夫が求められるでしょう。
おすすめの設計アプローチ
運用が安定する設計をいくつか挙げます。
- 色は「surface / text / accent / border」の4系統に分けて命名する
- テーマの追加は
[data-theme="..."]のブロックを1つ追加するだけで完結させる prefers-color-schemeを尊重しつつ、ユーザーが任意で上書きできる導線を用意する- フォールバック値を
var(--color-bg, #ffffff)のように必ず付ける - 色の決定版を1か所に集め、トークンとしてドキュメント化する
これらのポイントを押さえれば、後からテーマを追加する際の手間が大きく削減できます。
コーディングイベントでの設計議論を振り返ると、ハッカソンでのアイデア整理フレームワークで触れたように、初期設計の整理が後工程の負担を左右します。CSSカスタムプロパティもまさに同じで、最初に軸を決めておけば拡張は容易です。
Webデザイナーとしてのキャリアを振り返ると、福岡から東京に移ったタイミングで設計手法が大きく変わりました。働き方や環境の変遷は福岡から東京への転職記事にも綴っています。テーマ切り替えのような仕組みを日々の制作に少しずつ取り入れていくところから始めてみてください。