Documentation

πŸŒ‘ Β Dark and πŸŒ• Β Light mode with auto detection made easy with NuxtJS

Try switching: Β 

Features

  • Add .${color}-mode class to <html> for easy CSS theming
  • Force a page to a specific color mode (perfect for incremental development)
  • Works with any NuxtJS target (static or server) and rendering (universal and spa)
  • Auto detect the system color-mode
  • Sync dark mode across tabs and windows πŸ”„
  • Supports IE9+ πŸ‘΄

Live demo

nuxt-color-mode

Checkout the online demo.

Setup

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 buildModules section of your nuxt.config.js

nuxt.config.js
{
  buildModules: [
    '@nuxtjs/color-mode'
  ]
}

Use the modules property instead of buildModules if:

  • you are using ssr: false and nuxt start, see #25
  • you are using nuxt < 2.9.0

You are ready to start theming your CSS with .dark-mode and .light-mode classes ✨

Usage

It injects $colorMode helper with:

  • preference: Actual color-mode selected (can be 'system'), update it to change the user preferred color mode
  • value: Useful to know what color mode has been detected when $colorMode === 'system', you should not update it
  • unknown: Useful to know if during SSR or Generate, we need to render a placeholder
  • forced: 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>

<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:

pages/light.vue
<template>
  <h1>This page is forced with light mode</h1>
</template>

<script>
export default {
  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 example/ directory or play online with the CodeSandBox below:

Loading CodeSandbox...

Configuration

You can configure the module by providing the colorMode property in your nuxt.config.js, here are the default options:

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'. If no-preference is detected or the browser does not handle color-mode, it will set the fallback 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 Dark Mode

Tailwind v1.8+

Tailwind v1.8 introduced dark mode support, in order to work with @nuxtjs/color-mode, you need to set dark: 'class' in your tailwind.config.js:

// tailwind.config.js
module.exports = {
  experimental: {
    darkModeVariant: true
  },
  dark: 'class'
}

Then in your nuxt.config.js, set the classSuffix option to an empty string:

// nuxt.config.js
export default {
  // ...
  colorMode: {
    classSuffix: ''
  }
}

Checkout the live example on CodeSandBox.

Tailwindcss 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.

Contributing

You can contribute to this module online with CodeSandBox:

Edit @nuxtjs/color-mode

Or locally:

  1. Clone this repository
  2. Install dependencies using yarn install or npm install
  3. Start development server using yarn dev or npm run dev

License

MIT License

Copyright (c) NuxtJS Team