Enable or disable dark mode in Nuxt 3 with NuxtUI v2 and Tailwind with this easy plugin

a close up of a computer screen with many lines of code on it

I love dark mode. With a few exceptions, all of the websites I visit, program, or use as apps on my iPhone have dark mode enabled. When it comes to Nuxt 3, my favorite front-end meta-framework, it can only be just a setting in the nuxt.conf.ts file.

Or not?

Well, that’s what I thought, to be honest. Nuxt is famous for its great developer experience (DX), and I’d say it’s the most intuitive full-stack JavaScript framework out there.

tl;dr

export default defineNuxtPlugin((nuxtApp) => {
  const colorMode = useColorMode()
  nuxtApp.hook('app:mounted', () => {
    colorMode.preference = 'light'
    colorMode.value = 'light'
  })
})
TypeScript

The Problem

I’m working on a site where—for a change—I’d like to turn the dark mode off. However, the default settings enabled the dark mode, so I had to find out how to disable it.

As said, I was expecting a single option in the nuxt.conf.ts, or even app.conf.ts, but neither of those was the case. Alright, I thought, then let’s head to NuxtUI’s documentation. Documentations by Nuxt are usually concise and make it easy to digest even difficult topics.

So, I headed there and found: nothing. GPT-4o and even o1 couldn’t help me either, so I had to do it the old way: Google.

I stumbled upon this easy and makes-sense code for the aforementioned nuxt.conf.ts, but this didn’t solve the issue:

// NOT working in NuxtUI v2
colorMode: {
  preference: 'light'
}
TypeScript

The Solution

I found the solution in NuxtUI’s GitHub repository. An issue, marked for some reason as “question,” dating back to May 2023 but has been updated in November 2024, had the answer.

Specifically, user xak2000 came up with the easy but in my eyes still odd solution:

  1. Create a folder named plugins in your Nuxt’s root directory
  2. Create a file, either a .js or a .ts one, and register it as a Nuxt plugin with the following code:
export default defineNuxtPlugin((nuxtApp) => {
  const colorMode = useColorMode()
  nuxtApp.hook('app:mounted', () => {
    colorMode.preference = 'light'
    colorMode.value = 'light'
  })
})
TypeScript

I added a few inline documentation, because I like documented code, so the file in /plugins/disableDarkMode.client.ts looks like this in my project:

/**
 * Nuxt.js plugin to set the color mode to 'light' when the app is mounted.
 *
 * @param {Object} nuxtApp - The Nuxt application instance.
 */
export default defineNuxtPlugin((nuxtApp) => {
	// Get the color mode object from the useColorMode composable
	const colorMode = useColorMode()

	// Hook into the 'app:mounted' event to set the color mode to 'light'
	nuxtApp.hook('app:mounted', () => {
		colorMode.preference = 'light'
		colorMode.value      = 'light'
	})
})
TypeScript

xak2000 and johnnyicon in the comment below explained in relatively great detail why this is necessary. I’ll quote the main part of why Nuxt needs a plugin to disable Tailwind’s dark mode:

The problem with this solution is that if some user already opened the page with system color mode (i.e. before changing this config), it is already saved into the localStorage of the user’s browser and this value from the local storage has precedence over the value we set in the nuxt config. So, it is not really “force disable”.

The solution described here is not practical in this case because there is no one central place to call definePageMeta that every page will respect. Using a layout could help, but definePageMeta is not allowed to be used in layouts. It can be used only in pages.