Nuxt.jsでダークモードの切り替えスイッチを導入する方法について簡単にまとめました。
2.15.7
@nuxtjs/color-mode
https://color-mode.nuxtjs.org/
こちらですが、最新盤はNuxt3系の対応となっていますので、Nuxt2系でインストールする際はバージョンを指定するようにします。
npm i @nuxtjs/color-mode@2.1.1
Nuxt2系で普通にインストールするとバグってなにもできません。
私はここで時間をけっこう溶かしてしまいました。
インストールしたらnuxt.config.jsに追記しましょう。
{
buildModules: [
'@nuxtjs/color-mode'
]
}
NuxtColorModeはシンプルなモジュールで、$colorMode.preference
プロパティをグローバルに管理し、html全体にクラスを付与してくれるようです。
this.$colorMode.preference = 'dark'
という風にすると、html全体にdark-mode
というクラス、this.$colorMode.preference = 'light'
というようにすると、light-mode
というクラスが付与されます。
例えばトグルスイッチに応じて、切り替える場合は以下のようになります。
// components/ColorModeSwitch.vue
<template>
<div>
<input id="toggle" class="toggle-input" type='checkbox' v-model="isDarkMode" @change="toggleColorMode" />
<label for="toggle" class="toggle-label" />
</div>
</template>
<script>
export default {
data() {
return {
isDarkMode: false
}
},
methods: {
toggleColorMode() {
if (this.isDarkMode) {
this.$colorMode.preference = 'dark'
} else {
this.$colorMode.preference = 'light'
}
}
}
}
</script>
<style scoped>
.toggle-input {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
z-index: 5;
opacity: 0;
display: none;
}
.toggle-label {
display: inline-block;
width: 40px;
height: 20px;
background-color: #CBD5E0;
position: relative;
border-radius: 46px;
transition: 0.4s;
box-sizing: border-box;
cursor: pointer;
}
.toggle-label::after {
content: '';
position: absolute;
width: 20px;
height: 20px;
border-radius: 100%;
left: 0;
top: 0;
z-index: 2;
background: #fff;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
transition: 0.4s;
}
.toggle-input:checked+.toggle-label {
background-color: #718096;
}
.toggle-input:checked+.toggle-label::after {
left: 20px;
}
</style>
ブール変数isDarkMode
にtoggleチェックボックスをバインドさせておきます。
値がチェンジした際に、methodsでモードを切り替えるイメージです。
ここの部分ですね。
<input id="toggle" class="toggle-input" type='checkbox' v-model="isDarkMode" @change="toggleColorMode" />
チェックされるとmethodsのtoggleColorModeが呼ばれ、htmlにクラスを付与します。
methods: {
toggleColorMode() {
if (this.isDarkMode) {
this.$colorMode.preference = 'dark'
} else {
this.$colorMode.preference = 'light'
}
}
}
あとはヘッダーコンポーネントに配置します。
// components/Header.vue
<template>
<header class="header">
<nuxt-link :to='`/`'>
<h1 class="site-title">
Qlitre's Blog
</h1>
</nuxt-link>
<nav class="nav">
<ul class="main-nav">
...
<li class="nav-item">
<ColorModeSwitch />
</li>
</ul>
</nav>
</header>
</template>
トグルボタンをクリックするとトップのhtml要素に<html lang="ja" class="dark-mode">
というようにクラスが付与されます。
後はdark-modeの場合の色分けのスタイルを記述するだけです。
例えば背景色を変える場合。
/* これはライトモードのスタイル */
body {
background-color: #EDF2F7;
}
/* これはダークモードのスタイル */
.dark-mode body {
background-color: #1A202C;
}
ここは結構地道な作業となります。