はじめに
パソコンのディスプレイを長時間見ていると目が疲れます。背景色が白で文字が黒(いわゆるライトモード)というのが一般的ですが、背景の白が眩しくて辛い。筆者は、ダークモード(背景が黒系で文字が白系)が設定できる場合は好んで設定しています。この方が目に優しい。アイキャッチなどの写真も、背景が黒の方が良い感じに見れると思います。
筆者の Blog サイトもダークモード対応を行いました。(2024年3月13日から対応)画面右上の太陽または月アイコンをクリックする事でライトモードとダークモードを切り替えられます。
上のキャプチャ画像は、スマホサイズでのものです。このページを見に来てくれる方は PC の人が多いのですが、スマホ対応もしています。スマホの場合は、PC の時に表示する右側のサイドメニューを表示しません。その代わりに画面右上のハンバーガーメニュー(横3本線のアイコン)をタップする事で、PC のサイドメニューと同様のメニューを表示します。
Tailwind CSS の設定
Tailwind CSS は、CSS フレームワークです。公式のホームページを貼っておきます。公式のドキュメントは見易く、情報も多いのでコーディング時に良く参照しています。
HTMLから離れることなく、モダンなウェブサイトを素早く構築できます。
https://tailwindcss.com/
筆者はちゃんと使い始めてから半年程度です。慣れてくるに従って、便利で手放せないようになりました。今回は、Tailwind を使ってダークモードを実装しました。以下、Next.js と、SvelteKit 両方でダークモードの実装について説明します。
Next.js の場合
Next.js には「next-themes」というライブラリが有るので、これを利用しました。参考にさせていただいたサイトを次に貼るので、具体的にはそちらをご覧ください。
Next.js で next-themes と Tailwind CSS を使って Light/Dark モードを切り替える
https://goodpatch-tech.hatenablog.com/entry/next-themes-tailwind
SvelteKit の場合
SvelteKit の場合は、筆者の実装を紹介しておきます。Tailwind がインストールされていない場合は、次のサイトを参考にインストールします。
Install Tailwind CSS with SvelteKit
https://tailwindcss.com/docs/guides/sveltekit
tailwind.config.js 編集
tailwind.config.js を次のように編集します。
/** @type {import('tailwindcss').Config} */
export default {
content: ['./src/**/*.{html,js,svelte,ts}'],
darkMode: 'class',
以下省略
システムまたは web ブラウザの設定に従うだけならば、darkMode: ‘media’ で良く、以下の設定は不要となります。筆者はモード切替を手動で行いたかったので class にしています。
テーマ切り替えボタン実装
テーマ切り替えボタンのコンポーネントを実装して配置します。筆者の実装を例として紹介します。
src/lib/ThemeSwitch.svelte
<script lang="ts">
let isDark;
const toggleDarkMode = () => {
const html = document.documentElement;
isDark = html.classList.contains('dark')
if (isDark) {
html.classList.remove('dark')
localStorage.setItem('darkMode', 'false')
} else {
html.classList.add('dark')
localStorage.setItem('darkMode', 'true')
}
}
</script>
<button
aria-label="Toggle Dark Mode"
on:click={() => toggleDarkMode()}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="h-6 w-6 text-gray-900 dark:text-gray-100"
>
{#if !isDark}
<path
fillRule="evenodd"
d="M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z"
clipRule="evenodd"
/>
{:else}
<path d="M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z" />
{/if}
</svg>
</button>
上記コードでボタンをクリック・タップした時にモード切り替えを行います。切り替えたモードは、localStorage に保存も行います。ページを開きなおした時に、localStorage を参照してダークモードだった場合は、ダークモードで表示させるため次のコードも必要です。(赤字の部分)
src/app.html
<!doctype html>
<html lang="ja">
<head>
<meta charset="utf-8" />
(途中省略)
<script>
if (typeof window !== 'undefined' && window.localStorage) {
const darkMode = localStorage.getItem('darkMode');
if (darkMode === 'true') {
document.documentElement.classList.add('dark');
}
}
if (typeof window !== 'undefined' && window.matchMedia) {
const darkMode = window.matchMedia('(prefers-color-scheme: dark)').matches;
if (darkMode) {
document.documentElement.classList.add('dark');
}
}
</script>
%sveltekit.head%
</head>
(以下省略)
SvelteKit のホームページを少しいじって、このボタンを表示するようにしてみます。
src/routes/+page.svelte
<script lang="ts">
import ThemeSwitch from "$lib/ThemeSwitch.svelte";
</script>
<div class="p-4 dark:bg-zinc-800">
<ThemeSwitch />
<p class="text-3xl font-bold dark:text-lime-300">
ほげhoge
</p>
</div>
「npm run dev」コマンドでプログラムを実行し、ブラウザで確認してみます。
アイコンをクリックする度にモードが切り替わります。
ダークモードのスタイルを追加
筆者の場合はサイトを公開した後からダークモードを追加しました。そのため、ダークモードのスタイルを追加していく作業が必要で、この作業の方が大変でした。(ダークモード切り替えの仕組みはプログラムなので、理解してしまえば簡単な作業に思えます)
具体的には class=”…. dark:text-lime-300″ のようにダークモード時の色を追加する必要があります。前章のサンプルでは表示文字 (ほげhoge) に、最初から dark:text-lime-300 を入れておきました。この指定が無い場合は黒い文字のままなので、背景色に埋もれてほぼ見えない状態になってしまいます。
終わりに
簡単な紹介のつもりで記事を書き始めました。Next.js については既に分かりやすい記事が多かったので、参考にさせて頂いたサイトの紹介で済ませました。しかし、SvelteKit については記事自体も少なかったので、筆者の実装も含めて具体的に書く結果となりました。少しでも参考になれば幸いです。
【おまけ】本記事のアイキャッチ
ダークモードで黒いものと考えたら「イカ墨パスタ」を連想しました。アイキャッチの写真は、だいぶ前に筆者が撮影したものです。夏の旅行で妙高に宿泊していた時、日本海側へドライブに出掛けて昼食に頂きました。カニ寿司を食べたのですが、あまり見かけない「イカ墨焼きそば」を発見したので頼んでみました。お約束で、口の中とか真っ黒になるのを見たり見せたりして遊んでました。この年の夏はかなり暑くて、食事を終えて車に戻ってみたら、クルマの温度計が上限値を超えたエラー表示をしていました。普段だと、ここまで高温にならないのでこの時初めて見ました。