Hi! My name is SyL 👋
This is where I invite you to explore my journey as a solo entrepreneur. Join me on this adventure 🚀, where I share valuable insights and experiences to empower your entrepreneurial path. 🌟

Add dark mode to your Nuxt 3 app in 15 mins

I'll show you how to add dark mode to your Nuxt app quickly with VueUse and TailwindCSS.

Written by
Published on
06 Oct 2023


👋 Hi all, we will be extending our blog to add dark mode to it but this will apply to any Nuxt 3 app easily as well.

Dark mode

If you are following us from our creating a blog articles, you should already have Tailwind and VueUse installed and you can skip to Setting up Tailwind for dark mode.

Styling with Tailwind CSS

We will be using Tailwind CSS to style our blog including dark mode. Installation is made easy with Nuxt Tailwind by running this command in your terminal.

pnpm i -D @nuxtjs/tailwindcss

When installation is completed, load the package in the nuxt.config.ts file

// nuxt.config.tsexport default defineNuxtConfig({  modules: ["@nuxtjs/tailwindcss"],});

✨ That's it! We now have the power to style our blog including dark mode and all we need is to implement the logic for auto and manual selection of the mode.

Using VueUse

We will be using the VueUse pacakge that has a collection of composition utilities with one that will help us to implement the dark mode logic. To install the VueUse package, run the following command in a terminal inside your project folder.

pnpm i -D @vueuse/nuxt @vueuse/core

Once completed, make sure to add the package inside your nuxt.config.ts file.

//nuxt.config.tsexport default defineNuxtConfig({  modules: ["@nuxtjs/tailwindcss", "@vueuse/nuxt"],});

Setting up Tailwind for dark mode

Let's setup Tailwind CSS to be ready for dark mode! Head over to tailwind.config.js file and input the following:

//tailwind.config.js/** @type {import('tailwindcss').Config} */export default {  darkMode: "class", // Add this line for dark mode  // of the code};

Update your layout for dark mode

We can now use Tailwind CSS for dark mode and I will be applying it in our layouts/Default.vue file for a dark background.

//layouts/Default.vue<template>  <div class="min-h-screen dark:bg-gray-900"> <!-- Added dark:bg-gray-900 for dark mode -->    <!-- of the code -->  </div></template>

Toggling color mode

I will be using the Heroicons by Tailwind as the button to toggle between dark and light mode. You can install it with the command below in a terminal in your Nuxt project.

pnpm install @heroicons/vue

We can now use the icons and I will be adding it inside components/SiteHeader.vue of our blog app, but you can do so at any vue file.

//components/SiteHeader.vue<script lang="ts" setup>import { SunIcon, MoonIcon } from "@heroicons/vue/24/solid"; // Import our heroicons for useconst isDark = useDark(); // VueUse function to initialize and check if its dark modeconst toggleDark = useToggle(isDark); // VueUse function to toggle between the color mode</script><template>  <header>        <!-- of the code  -->    <div class="max-w-lg mx-auto flex justify-center my-3">      <button        class="rounded-md p-1.5 transition-colors hover:bg-gray-100 dark:text-gray-200 dark:hover:bg-gray-800"        aria-label="Change color mode"        @click="toggleDark()"      >         <client-only> <!-- This is to make sure the right icon is render only in client-side -->          <MoonIcon class="h-5 w-5" v-if="isDark" />          <SunIcon class="h-5 w-5"  v-else/>        </client-only>      </button>    </div>  </header></template>

✨ We have now succesfully added dark mode to our app and you should see the background turn dark! Reload the page and notice that the dark mode stays even after reloading. That's because VueUse useDark function persist the data using localStorage.

However, you will also notice that the rest of the content are not yet styled for the dark mode. You can use the useDark function and Tailwind CSS dark: syntax to style them like what we did for the background.

Color mode bug on reload

If you reload the page in dark mode, you will notice that the light mode flashes for a second before the page turn dark. That's because our useDark initialization is called after the page finish loading. Hence we will need to find a way to initialize it before the page load.

To do so, we will add javascript to our Nuxt app in the <head> tag ensuring the color mode is set correctly before the page finish loading. You can check out this article here on ways to do so. I will be using the useHead method in our app.vue file.

//app.vue<script setup lang="ts">useHead({  script: [    {      children: `localStorage.getItem("vueuse-color-scheme") == 'dark'     ? document.documentElement.classList.add("dark")     : document.documentElement.classList.remove("dark");`,    },  ],  });</script><template>  <NuxtLayout>    <NuxtPage />  </NuxtLayout></template>

In our code, we retrieve the value of vueuse-color-scheme from the localStorage and add the dark class to our html tag. This is actually what useDark does under the hood where it save the dark mode value under vueuse-color-scheme.

✨ Reload the page now and you can see that the white flash is gone! We have now successfully added dark mode to our app!

What's next?

Download the complete code here at Github.

Check out more related articles below!

Create a Nuxt 3 Content blog with Tailwind CSS in one hour.
3 ways to add javascript in the head tag of your Nuxt 3 app.
Add table of contents to your Nuxt 3 blog in 10 mins.
Deploy your Nuxt 3 app with Vercel for free in 5 mins