Nuxt Color Mode
Dark and Light mode with auto detection made easy with Nuxt ๐
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
- Supports IE9+ ๐ด
Live demo
Checkout the online demo and source code.
Setup
@nuxtjs/color-mode
is compatible with Nuxt 3 and Nuxt Bridge. If you're looking for the previous version of this module, check out v2.color-mode.nuxtjs.org, or read more about the differences.
Add @nuxtjs/color-mode
dependency to your project:
yarn add --dev @nuxtjs/color-mode
Then, add @nuxtjs/color-mode
to the modules
section of your nuxt.config.ts
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 Bridgeexport default { colorMode: 'light',}// For Nuxt 3definePageMeta({ colorMode: 'light',})</script>
This feature is perfect for implementing dark mode to a website incrementally by setting the not-ready pages to colorMode: 'light'
.
$colorMode.forced
value.Configuration
You can configure the module by providing the colorMode
property in your nuxt.config.js
; here are the default options:
import { defineNuxtConfig } from 'nuxt'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 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.ts
, set the classSuffix
option to an empty string:
export default defineNuxtConfig({ modules: ['@nuxtjs/color-mode'], colorMode: { classSuffix: '' }})
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',- }+ <script setup>+ definePageMeta({+ colorMode: 'light',+ })</script>
โ ๏ธ If you are using Nuxt Bridge, you should not use definePageMeta
but instead continue using the component option colorMode
.
- 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