Documentation
Dark and Light mode with auto detection made easy with Nuxt 🌗
v3 of @nuxtjs/color-mode
is compatible with Nuxt 3 and Nuxt Bridge. If you're looking for the previous version of this module, check out the previous docs, or read more about the differences.
Features
- Nuxt 3 and Nuxt Bridge support
- Add
.${color}-mode
class to<html>
for easy CSS theming - Force a page to a specific color mode (perfect for incremental development)
- Works with client-side and universal rendering
- Auto detect system color-mode
- Sync dark mode across tabs and windows 🔄
- Supports IE9+ 👴
Live demo
Checkout the online demo.
Setup
@nuxtjs/color-mode
version 3 supports Nuxt Bridge and Nuxt 3 only. For use in Nuxt 2 (without Bridge), make sure to install version 2.
Add @nuxtjs/color-mode
dependency to your project:
yarn add --dev @nuxtjs/color-mode
npm install --save-dev @nuxtjs/color-mode
Then, add @nuxtjs/color-mode
to the modules
section of your nuxt.config.js
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
modules: ['@nuxtjs/color-mode']
})
You are ready to start theming your CSS with .dark-mode
and .light-mode
classes ✨
Usage
You can access the color mode helper by either calling useColorMode()
or accessing $colorMode
directly in your template. This helper has the following properties:
preference
: Actual color-mode selected (can be'system'
), update it to change the user preferred color modevalue
: Useful to know what color mode has been detected when$colorMode === 'system'
, you should not update itunknown
: Useful to know if during SSR or Generate, we need to render a placeholderforced
: Useful to know if the current color mode is forced by the current page (useful to hide the color picker)
<template>
<div>
<h1>Color mode: {{ $colorMode.value }}</h1>
<select v-model="$colorMode.preference">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
<option value="sepia">Sepia</option>
</select>
</div>
</template>
<script setup>
const colorMode = useColorMode()
console.log(colorMode.preference)
</script>
<style>
body {
background-color: #fff;
color: rgba(0,0,0,0.8);
}
.dark-mode body {
background-color: #091a28;
color: #ebf4f1;
}
.sepia-mode body {
background-color: #f1e7d0;
color: #433422;
}
</style>
Force a color mode
You can force the color mode at the page level (only parent) by setting the colorMode
property:
<template>
<h1>This page is forced with light mode</h1>
</template>
<script>
// For Nuxt Bridge
export default {
colorMode: 'light',
}
// For Nuxt 3
definePageMeta({
colorMode: 'light',
})
</script>
This feature is perfect for implementing dark mode to a website incrementally by setting the not-ready pages to colorMode: 'light'
.
We recommend to hide or disable the color mode picker on the page since it won't be able to change the current page color mode, using $colorMode.forced
value.
Example
You can see a more advanced example in the playground/ directory or play online with the CodeSandBox below:
Configuration
You can configure the module by providing the colorMode
property in your nuxt.config.js
; here are the default options:
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
modules: ['@nuxtjs/color-mode'],
colorMode: {
preference: 'system', // default value of $colorMode.preference
fallback: 'light', // fallback value if not system preference found
hid: 'nuxt-color-mode-script',
globalName: '__NUXT_COLOR_MODE__',
componentName: 'ColorScheme',
classPrefix: '',
classSuffix: '-mode',
storageKey: 'nuxt-color-mode'
}
})
Notes:
'system'
is a special value; it will automatically detect the color mode based on the system preferences (see prefers-color-mode spec). The value injected will be either'light'
or'dark'
. Ifno-preference
is detected or the browser does not handle color-mode, it will set thefallback
value.
Caveats
When $colorMode.preference
is set to 'system'
, using $colorMode
in your Vue template will lead to a flash. This is due to the fact that we cannot know the user preferences when pre-rendering the page since they are detected on client-side.
To avoid the flash, you have to guard any rendering path which depends on $colorMode
with $colorMode.unknown
to render a placeholder or use our <ColorScheme>
component.
Example:
<template>
<ColorScheme placeholder="..." tag="span">
Color mode: <b>{{ $colorMode.preference }}</b>
<span v-if="$colorMode.preference === 'system'">(<i>{{ $colorMode.value }}</i> mode detected)</span>
</ColorScheme>
</template>
Props:
placeholder
:String
tag
:String
, default:'span'
TailwindCSS
Tailwind v2
Tailwind v2 introduced dark mode, in order to work with @nuxtjs/color-mode
, you need to set darkMode: 'class'
in your tailwind.config.js
:
module.exports = {
darkMode: 'class'
}
Then in your nuxt.config.js
, set the classSuffix
option to an empty string:
import { defineNuxtConfig } from 'nuxt3'
export default defineNuxtConfig({
modules: ['@nuxtjs/color-mode'],
colorMode: {
classSuffix: ''
}
})
Checkout the live example on CodeSandBox.
Tailwind Dark Mode Plugin
You can easily integrate this module with tailwindcss-dark-mode by just setting darkSelector: '.dark-mode'
, see changing the selector documentation.
// tailwind.config.js
module.exports = {
theme: {
darkSelector: '.dark-mode'
},
variants: {
backgroundColor: ["dark", "dark-hover", "dark-group-hover", "dark-even", "dark-odd", "hover", "responsive"],
borderColor: ["dark", "dark-focus", "dark-focus-within", "hover", "responsive"],
textColor: ["dark", "dark-hover", "dark-active", "hover", "responsive"]
},
plugins: [
require('tailwindcss-dark-mode')()
]
}
Checkout a live example on CodeSandBox as well as @nuxtjs/tailwindcss module.
Migrating to v3
v3 of @nuxtjs/color-mode
requires either Nuxt Bridge or Nuxt 3. (If you are using Nuxt 2 without Bridge, you should continue to use v2.)
-
The main change between Nuxt 2 -> Nuxt 3 is that you will define your color mode at the page level with
definePageMeta
:<template> <h1>This page is forced with light mode</h1> </template> <script> - export default { - colorMode: 'light', - } + definePageMeta({ + colorMode: 'light', + }) </script>
⚠️ If you are using Nuxt Bridge, you should not use
definePageMeta
but instead continue using the component optioncolorMode
. -
The
$colorMode
helper remains the same, but there is also a new composable (useColorMode
) which is the recommended way of accessing color mode information. -
If you were directly importing color mode configuration types, note that this has been renamed to
ModuleOptions
.
Contributing
You can contribute to this module online with CodeSandBox:
Or locally:
- Clone this repository
- Install dependencies using
yarn install
ornpm install
- Start development server using
yarn dev
ornpm run dev
License
Copyright (c) Nuxt Team