Back to Blog
EngineeringJune 20, 20265 min read

Zero-Flicker Dark Mode in Next.js Server Components

Prevent layout shifts and flash-of-light-mode hydration errors using pre-hydration scripting.

AD
Abhinav Dash
Founder & Software Engineer

The Hydration Flash Problem

When using Next.js, pages are pre-rendered on the server. If your server renders the page in light mode, but the client prefers dark mode, the user will experience a momentary flash of bright white background before the theme synchronizes.

The Script Tag Fix

To solve this, inject a small, blocking JavaScript script into the <head> of the document before React starts hydrating the HTML.

<head>
  <script
    dangerouslySetInnerHTML={{
      __html: `
        try {
          if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
            document.documentElement.classList.add('dark');
          } else {
            document.documentElement.classList.remove('dark');
          }
        } catch (_) {}
      `,
    }}
  />
</head>

How it works

  1. The script runs synchronously immediately when it is parsed.
  1. It toggles the class `dark` on the root element.
  1. Because it executes before CSS layout rendering, the browser paints the dark theme background right away.
  1. No flashing, no layout shifts, and no hydration errors.