next-themes: System preference doesn't work by default

When I read the docs it looks like system preference is set to true by default.

enableSystem = true: Whether to switch between dark and light based on prefers-color-scheme

But when I implement this or just browse the demo https://next-themes-example.vercel.app/ or the one with Tailwind — even though my macOS preference is set to dark, the theme gets set to light.

This doesn’t look like a sane default or a bug. My thought process is that next-themes would by default prefer the system’s preference when available and only fallback to light if it’s not.

Am I doing something wrong?

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 16 (5 by maintainers)

Most upvoted comments

I published 0.0.13-beta.1 with the following changes:

  • system is now the default theme is enableSystem === true, otherwise it’s still light
  • The default theme is not immediately saved to localStorage on first load, only when you switch theme

These should resolve this issue. Please test, and let me know if you have any feedback.

Thanks for the response. I did read through the issue. It seems like a bad default. The main purpose of this library is to be able to adopt to the user preference since it doesn’t provide a UI (for setTheme which is a feature and is opt-in). Please consider making the system setting default.

My setup did start working I have no idea how. Bunch of cache removals and then setting themese manually etc — and now it works with:


<ThemeProvider attribute="class" defaultTheme="system" forcedTheme={Component.theme || undefined}>
			<Component {...pageProps} />
		</ThemeProvider>

But when I set Post.theme = light; — that page theme doesn’t change to the light theme.

If console log the the theme being forced

import { ThemeProvider } from 'next-themes';

function MyApp({ Component, pageProps }) {
	console.log(`Component.theme`, Component.theme);
	return (
		<ThemeProvider attribute="class" defaultTheme="system" forcedTheme={Component.theme || undefined}>
			<Component {...pageProps} />
		</ThemeProvider>
	);
}

export default MyApp;

Then it logs Component.theme light. This is not working because of the same caching issue?

This doesn’t look like a sane default or a bug. My thought process is that next-themes would by default prefer the system’s preference when available and only fallback to light if it’s not.

Am I doing something wrong?

Sounds like you’re running into the same issue as #15. The documentation states:

defaultTheme = 'light': Default theme name

So by default, your app will use light theme, not system. You can change this by setting defaultTheme (basically, just read through that issue as it’s the same discussion).


The second problem you’re running into is one I plan to fix shortly: the theme is cached into localStorage immediately. This means the first time you loaded the website, it cached light. Now, even though you’re changing defaultTheme, we are respecting the cache. Try calling setTheme or clearing the local storage cache yourself.

I’m going to remove this behavior, so that the theme isn’t cached until a call to setTheme has been made.