windicss 内では、メディアクエリとクラスの 2 つの方法でダークモードの適応が可能です。さらに便利なのは、提供されるdark
バリアントが選択した適応モードに応じて自動的にコードを生成するため、無駄な CSS を書くことを避けることができ、見やすくなります。
制御を容易にするために、クラスの方法を選択してダークモードを切り替えます(つまり、ルート要素にdark
クラスを割り当ててダークモードに切り替えます)
ベーススタイル#
まず、windicss ではカバーできないいくつかのグローバル CSS が必要です。
スクロールバーの色変更#
通常、-webkit-scrollbar
疑似クラスを使用したいと思うかもしれませんが、実はもっと優雅な方法があります。ブラウザはcolor-scheme
という CSS プロパティを提供しており、これを dark に設定すると、ブラウザ内のすべてのデフォルト要素がダークスタイルでレンダリングされます。
html.dark {
color-scheme: dark;
}
画像の明るさを下げる#
これも非常に簡単で、フィルターを適用するだけです。
html.dark img {
filter: brightness(0.8);
}
自動検出#
次は本命です。HTML 要素にdark
クラスを追加する方法を判断して実装する必要があります。なぜなら、windicss は自動的に処理してくれないからです。
ユーザーには、自動適応、ダークモードを維持、ライトモードを維持するためのドロップダウンメニューを提供します。
ページの初期読み込み時にスタイルの切り替えによるフラッシュを防ぐために、最終的にこの設定を cookie に保存することにしました。これにより、SSR の効果を発揮することができます。ユーザーがダーク / ライトを強制すると、サーバーはクラス名を HTML タグに書き込むことができます。
function readDarkModeInStorage() {
const darkMode = useCookie('darkMode')
const possibleValues = ['auto', 'dark', 'light']
if (darkMode.value && possibleValues.includes(darkMode.value)) {
return darkMode.value
} else {
return 'auto'
}
}
上記は、ストレージからダークモードの設定を読み取るためのヘルパー関数であり、サーバー / クライアントの両方で使用できます。
function setModeClass(isDark: boolean): void {
if (isDark) {
useHead({
htmlAttrs: { class: 'dark' },
meta: [{ name: 'theme-color', content: '#121212' }],
})
} else {
useHead({
htmlAttrs: { class: '' },
meta: [{ name: 'theme-color', content: '#ffffff' }],
})
}
}
ダークモードのスタイルを設定するためのユーティリティ関数であり、ブール値が渡されると、html のクラス名と theme-color のメタタグ(SSR/CSR の両方で使用可能)を同時に設定します。
VueUse から提供される useHead メソッドを使用しています。
const currentMode = ref(readDarkModeInStorage())
const preferredDark = usePreferredDark()
watchEffect(() => {
if (currentMode.value === 'auto') {
if (preferredDark.value) {
setModeClass(true)
} else {
setModeClass(false)
}
} else if (currentMode.value === 'dark') {
setModeClass(true)
} else if (currentMode.value === 'light') {
setModeClass(false)
}
useCookie('darkMode').value = currentMode.value
})
ここが重要です。まず、設定を読み込んでcurrentMode
変数に初期化します。次に、VueUse のusePreferredDark
を使用して現在のブラウザのカラーモードを取得します。
ウォッチエフェクトの関数を使用して、上記の 2 つの値が変更された場合にsetModeClass
ユーティリティ関数を呼び出して最終的なクラス名の変更を行い、設定を cookie に書き込みます。