How to Fix Dark Mode Flicker in Next.js (The Right Way)
The Problem
You toggle dark mode.
It works.
You refresh the page.
For a brief moment, the page appears in light mode… then switches to dark.
That flash is called FOUC — Flash of Unstyled Content.
Why does it happen?
Because:
Next.js renders HTML on the server.
The browser paints it.
JavaScript loads.
Your theme logic reads localStorage.
Then it switches to dark.
The browser always paints before JavaScript runs.
That tiny gap is the flicker.
The Correct Fix
You must set the theme before the browser paints.
That means inside your HTML.
In app/layout.tsx:
const themeScript = `
(function() {
try {
const stored = localStorage.getItem(’theme’);
const systemDark = window.matchMedia(’(prefers-color-scheme: dark)’).matches;
const theme = stored ? stored : (systemDark ? ‘dark’ : ‘light’);
document.documentElement.setAttribute(’data-theme’, theme);
} catch (e) {}
})();
`;And inject it inside <head>:
<head>
<script dangerouslySetInnerHTML={{ __html: themeScript }} />
</head>Now the theme is set before React hydrates.
No flicker.
Why This Works
Rendering order matters.
The browser:
Parses HTML
Runs inline scripts
Applies CSS
Paints
If the theme is decided in step 2, the first paint is correct.
If it’s decided in step 5 (React), you get flicker.
That’s the whole trick.

