Freshでダークモード対応をする
作成日
更新日
やること
- テーマ変更用Toggleを用意する
- island で実装する
- 全ページで状態の共有をする
- Signal で実装する
- 初期値はクライアント側の設定を利用する
Signal を用意する
signals/theme.ts
import { signal } from "@preact/signals";
export const theme = signal<"light" | "dark">("light");
Toggleを用意する
islandで実装。
islands/ThemeModeToggle.tsx
import { theme } from "../signals/theme.ts";
import { useEffect } from "preact/hooks";
export default function ThemeModeToggle() {
// 初期値を設定する
useEffect(() => {
const saved = localStorage.getItem("theme");
if (saved === "dark" || saved === "light") {
theme.value = saved;
document.documentElement.setAttribute("data-theme", saved);
}
}, []);
// 端末側で変更された場合にも更新する
useEffect(() => {
const mediaQuery = globalThis.matchMedia("(prefers-color-scheme: dark)");
const listener = (event: MediaQueryListEvent) => {
const systemPrefersDark = event.matches;
const newTheme = systemPrefersDark ? "dark" : "light";
document.documentElement.setAttribute("data-theme", newTheme);
localStorage.setItem("theme", newTheme);
};
mediaQuery.addEventListener("change", listener);
return () => mediaQuery.removeEventListener("change", listener);
}, []);
const toggleTheme = () => {
theme.value = theme.value === "light" ? "dark" : "light";
document.documentElement.setAttribute("data-theme", theme.value);
localStorage.setItem("theme", theme.value);
};
return (
<button onClick={toggleTheme} class="w-12 h-12 bg-theme bg-contain lg:fixed absolute top-0 right-0 p-2 m-2">
{theme.value === "dark" ? "" : ""}
</button>
);
}
Tailwindの設定
Tailwindでclassベースでダークモード切替できるようにする。
tailwind.config.ts
export default {
darkMode: "media",
};
media
を設定した場合は端末の設定に自動で追従する。
class
を設定した場合は dark:bg-gray
のようにしてdark
が使えるようになる。
配置する
<ThemeModeToggle />
CSSの設定
色は次のようにstyle.css
で変更する。
@layer base {
:root {
--main-text: #3c444d;
--main-background: #f8f8fc;
}
:root[data-theme="dark"] {
--main-text: #e3e3e7;
--main-background: #3c444d;
}
}

公開日
更新日