先日、にほんご。にダークモードを追加しました。 モノクロベースのサイトなのであまり労力をかけずに対応することができました。
ダークモードはCSSのprefers-color-scheme
を利用して、OSのテーマから判定するパターンが多いようですが、
にほんご。ではprefers-color-scheme
を使わず、サイト上で切り替えてもらうという実装にしました。
対応していないブラウザを利用しているユーザーや、Windows7以下を利用しているユーザーも多いため、
そういう環境のユーザーでもモード選択できるような環境にしておきたいと思い、この方法をとりました。
今回はその実装方法を紹介したいと思います。
まずはページ作成
まずは適当にページを作成します。
link
タグを2つ用意しました。
1つはmain.css
を読み込みます。こちらはページのレイアウトだったり、文字サイズ等、テーマ(色)とは関係無いスタイルを定義します。
2つめはテーマを指定するためのタグです。このタグにはJavaScriptでCSSを判定させます。そのためJSで操作しやすいようにid
を設定しておきます。
ついでにhref
を空にしてあります。
head
タグ内のscript
にはテーマ切り替え用スクリプトを定義します。これについては後ほど解説します。
HTML
<!DOCTYPE html>
<head>
<link id="theme_style" rel="stylesheet" type="text/css" href="" />
<link rel="stylesheet" type="text/css" href="main.css" />
<script id="srcTheme" src="toggleTheme.js"></script>
<style>
</style>
</head>
<body>
<div id="text">テキスト</div>
<div id="box1">ボックス1</div>
<div id="box2">ボックス2</div>
<br>
<div id="toggleTheme">
<svg role="img" width=16 height=16 xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512">
<path d="M8 256c0 136.966 111.033 248 248 248s248-111.034 248-248S392.966 8 256 8 8 119.033 8 256zm248 184V72c101.705 0 184 82.311 184 184 0 101.705-82.311 184-184 184z"></path>
</svg>
</div>
</body>
</html>
CSSを作成
次にCSSを作成します。今回の例では3つのファイルを作成します。
main.css
- レイアウト定義
light.css
- ライトモード
dark.css
- ダークモード
main.css
#box1,
#box2 {
width: 100px;
height: 100px;
margin: 10px;
}
#box2 {
border: solid 1px;
}
#toggleTheme:hover {
cursor: pointer;
}
light.css
body {
color: #000;
background-color: #fff;
}
#box1 {
color: #fff;
background-color: #000;
}
#box2 {
border-color: #fff;
}
#toggleTheme svg {
fill: #666;
}
dark.css
body {
color: #e0e0e0;
background-color: #222;
}
#box1 {
color: #222;
background-color: #e0e0e0;
}
#box2 {
border-color: #222;
}
#toggleTheme svg {
fill: #bbb;
}
テーマ切り替え用スクリプト
テーマの切り替えはJavaScriptで行います。
以下のようにJSでlink
タグのhref
を指定すると、そのCSSが読み込まれます。
document.getElementById('theme_style').href = 'dark.css';
次にこのhref
をテーマの状態によって切り替える処理を追加したいのですがその前に、
テーマを切り替えた後、再度同じサイトに訪れた場合にも同じテーマが適用されて欲しいですね。
何らかの方法で指定したテーマを保存したいです。
データの保存はcookie
やsession
などの方法がありますが、今回はlocalStrage
を利用することにしました。
localStrage
はセキュアではなく、文字列しか保存できないので、大事なデータを扱うのには向いていません。
しかし、今回の例ではサーバを通して整合性をチェックする必要が無いですし、JSで扱いやすいので採用しました。
また、一度保存すると基本的に永続的に保存されるという点も大きいです。逆にそれがNGなパターンもあるかと思いますが。
localStrage
へのデータの保存は以下のように指定します。
localStorage.setItem('isDark', '1');
これでテーマ切り替えの素材は揃いましたのでロジックを組んでいきます。
localStorage
にisDark
があればdark.css
を読み込み、
無ければlight.css
を読み込みます。
そして、特定の要素をtoggleスイッチとして用意し、そのスイッチを押すとlocalStorage
のisDark
を保存/削除するようにします。
具体的には以下のような処理になります。
toggleTheme.js
setThemeFile = function() {
if (localStorage.getItem('isDark') === '1') {
document.getElementById('theme_style').href = 'dark.css';
} else {
document.getElementById('theme_style').href = 'light.css';
}
}
toggleDLMode = function() {
if (localStorage.getItem('isDark') === '1') {
localStorage.removeItem('isDark');
} else {
localStorage.setItem('isDark', '1');
}
setThemeFile();
}
setThemeFile();
window.addEventListener('load', function() {
document.getElementById('toggleTheme').addEventListener('click', toggleDLMode);
});
ここでのポイントはsetThemeFile()
をaddEventListener
のload
の外に置いてある点です。
setThemeFile()
を中に入れてしまうと、全ての要素が読み込まれた後にCSSファイルが読み込まれます。
環境によってはすべてのDOMが読み込まれた後にCSSが指定されることになり、一瞬チラついてしまうことがあります。
それを極力減らすためにsetThemeFile()
を外に出して、DOMが読み込まれる前にCSSを指定しています。
これでダークモード対応とモードを切り替える処理を実装することができました。
Webサイトへのダークモードの実装は徐々に増えてきています。
サイト内で利用している色が多いとその分対応は難しいと思いますが、
ユーザーのことを考えれば早めに対応した方が良いのかもしれません。
ちなみにこのブログではしばらく対応しない予定です。
今回はprefers-color-scheme
を使わない例を紹介しましたが、
サイトの特性に合わせて実装方法を検討すれば良いかと思います。