はじめに
便利なCSSカスタムプロパティ。実はJavaScriptから取得/設定ができます。今回はCSSカスタムプロパティとJavaScriptを使ってモード切替(配色変更)を実装する方法を解説します。
CSSカスタムプロパティ
CSSカスタムプロパティとはCSS内で使用できる変数のことです。
Webデザインの配色を考えるとき、たくさんの色を使うことは滅多にありません。大抵は白色+黒色+テーマカラー(1〜2色)に落ち着くことと思います。
テーマカラーはWeb全体のあちこちに配色されることになります。見出しの文字色だったり、ボックスの背景色だったり、表の罫線だったり、というように。
// テーマカラーが #417ece の場合
h1 {
color: #417ece;
}
.box {
background-color: #417ece;
}
.cell {
border-bottom: 1px solid #417ece;
}
このように分散して書いていると、いざテーマカラーを変更したいとなったときに修正が非常に面倒です。一括置換すれば楽ですが、対象が複数ファイルに及ぶとやはり面倒です。
そこで登場するのがCSSカスタムプロパティです。テーマカラーをCSSカスタムプロパティに入れてやることで面倒な修正作業から解放されます。
// テーマカラーが #417ece の場合
// CSSカスタムプロパティ
:root {
--theme-color: #417ece;
}
h1 {
color: var(--theme-color);
}
.box {
background-color: var(--theme-color);
}
.cell {
border-bottom: 1px solid var(--theme-color);
}
テーマカラーを変更したいときは一番上の--theme-color
を変更するだけで済みます。
ちなみに:root
というのは擬似クラスのひとつで、文書のルート要素、つまりhtml
タグのことを指します。CSSカスタムプロパティは:root
内に書くというのが慣習になっています。
rgba、lighten、darkenとの併用
CSSカスタムプロパティとlighten
、darken
との併用はできません。また、rgba
は16進数のCSSカスタムプロパティは使えなくて、RGB値のCSSカスタムプロパティであれば使えます。
:root {
--theme-color: #417ece;
// RBB値(「rgb(65, 126, 206)」という書き方はNG)
--theme-color-rgb: 65, 126, 206;
}
.heading {
// ❌ lighten、darkenはCSSカスタムプロパティを使えない
background-color: lighten(var(--theme-color), 50%);
border-bottom: 1px solid darken(var(--theme-color), 50%);
// ❌ 16進数のCSSカスタムプロパティは使えない
color: rgba(var(--theme-color), .5);
// ⭕ RGB値のCSSカスタムプロパティは使える
color: rgba(var(--theme-color-rgb), .5);
}
サンプル
簡単なものですがサンプルを作ったので動きを確認してみてください。左上の「モード切替」をクリックするたびにライトモードとダークモードが切り替わります。
実装
では、さっそく実装していきます。まず初めにすべてのコードを記載します。CSSはSASSを使用、JavaScriptはjQueryを使用していますのでご注意ください。
HTML
<span id="mode-toggle">モード切替</span>
<div id="wrap">
<h1>Sample Text</h1>
</div>
CSS
#mode-toggle {
cursor: pointer;
color: #000;
}
#wrap {
display: flex;
justify-content: center;
align-items: center;
width: 100vw;
height: 100vh;
color: var(--text-color);
background-color: var(--bg-color);
transition: color .5s, background-color .5s;
}
:root {
--mode:light;
--bg-color: var(--light-bg-color);
--text-color: var(--light-text-color);
// Light Mode
--light-bg-color: #fff;
--light-text-color: #000;
// Dark Mode
--dark-bg-color: #000;
--dark-text-color: #fff;
}
JavaScript
const modeToggle = () => {
$('#mode-toggle').on('click', function() {
const html = document.querySelector('html');
const currentMode = getComputedStyle(html).getPropertyValue("--mode");
let mode = null, bgColor = null, textColor = null;
switch (currentMode) {
case 'light':
mode = 'dark';
bgColor = getComputedStyle(html).getPropertyValue("--dark-bg-color");
textColor = getComputedStyle(html).getPropertyValue("--dark-text-color");
break;
case 'dark':
mode = 'light';
bgColor = getComputedStyle(html).getPropertyValue("--light-bg-color");
textColor = getComputedStyle(html).getPropertyValue("--light-text-color");
break;
default:
break;
}
html.style.setProperty('--mode', mode);
html.style.setProperty('--bg-color', bgColor);
html.style.setProperty('--text-color', textColor);
});
}
$(function() {
modeToggle();
});
解説
HTML
特筆すべきことはありません。
CSS
#wrap {
color: var(--text-color);
background-color: var(--bg-color);
}
#wrap
の文字色と背景色にCSSカスタムプロパティを使用しています。
:root {
--mode:light;
--bg-color: var(--light-bg-color);
--text-color: var(--light-text-color);
// Light Mode
--light-bg-color: #fff;
--light-text-color: #000;
// Dark Mode
--dark-bg-color: #000;
--dark-text-color: #fff;
}
実際に使用するCSSカスタムプロパティと、ライトモード/ダークモードそれぞれのCSSカスタムプロパティを用意しておきます。そして、最初に使用するモードのCSSカスタムプロパティを、実際に使用するCSSカスタムプロパティに設定します(今回はライトモード)。
--mode
は現在のモードを保持しておくためのCSSカスタムプロパティです。モードが切り替わるたびに値が変更されます。このとき、以下のことに気をつけてください(理由は後述)。
// ❌ プロパティ名と値の間にスペースは不要
--mode: light;
// ❌ 値をシングルクォーテーションやダブルクォーテーションで括らない
--mode:'light';
--mode:"light";
// ⭕ 必ず以下のように記述
--mode:light;
JavaScript
const modeToggle = () => {
$('#mode-toggle').on('click', function() {
#mode-toggle
がクリックされたときのイベントを記述しています。
const html = document.querySelector('html');
const currentMode = getComputedStyle(html).getPropertyValue("--mode");
1行目でhtml
要素を取得し、2行目で--mode
というCSSカスタムプロパティの値を取得しています。CSSカスタムプロパティの書き方によって取得される値が微妙に異なるので注意してください(後続の分岐処理に影響します)。
- ❌ プロパティ名と値の間にスペースがある
- CSSカスタムプロパティ:
--mode: light;
- 取得される値:
「 light」
※先頭にスペースがある
- CSSカスタムプロパティ:
- ❌ 値をシングルクォーテーションやダブルクォーテーションで括る
- CSSカスタムプロパティ:
--mode:'light';
/--mode:"light";
- 取得される値:
'light'
/"light"
- CSSカスタムプロパティ:
- ⭕ 正しく記述
- CSSカスタムプロパティ:
--mode:light;
- 取得される値:
light
- CSSカスタムプロパティ:
let mode = null, bgColor = null, textColor = null;
switch (currentMode) {
case 'light':
mode = 'dark';
bgColor = getComputedStyle(html).getPropertyValue("--dark-bg-color");
textColor = getComputedStyle(html).getPropertyValue("--dark-text-color");
break;
case 'dark':
mode = 'light';
bgColor = getComputedStyle(html).getPropertyValue("--light-bg-color");
textColor = getComputedStyle(html).getPropertyValue("--light-text-color");
break;
default:
break;
}
取得したモードの値によって処理を分岐しています。現在がライトモードならダークモードの値を取得し、現在がダークモードならライトモードの値を取得します。
html.style.setProperty('--mode', mode);
html.style.setProperty('--bg-color', bgColor);
html.style.setProperty('--text-color', textColor);
取得した値を設定しています。
まとめ
CSSカスタムプロパティとJavaScriptを使ってモード切替(配色変更)を実装することができました。意外と簡単に実装できたのではないでしょうか。
今回は実装しませんでしたが、Local Storageにモードの状態を保存しておくことで、次回アクセス時にもモードを保持しておくことが可能になります。
Local Storageについては、以下のページでも触れているので参考にしてください。