Part 44: Building a Dark Mode Toggle with LocalStorage & Zero Flicker

Part 44 Technology Updated September 12, 2026

Part 44: Building a Dark Mode Toggle with LocalStorage & Zero Flicker

When implementing manual dark mode, a common issue is the "White Flash of Death"—the page briefly renders in white before JavaScript reads localStorage and applies the dark class.


1. The Anti-Flicker Inline Script

Place this tiny script directly in your <head> tag in index.html before any CSS or body content renders:

<script>
  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');
  }
</script>

2. The Interactive Toggle Button

import { useState, useEffect } from 'react';

export default function DarkModeToggle() {
  const [isDark, setIsDark] = useState(false);

  useEffect(() => {
    setIsDark(document.documentElement.classList.contains('dark'));
  }, []);

  const toggleTheme = () => {
    if (isDark) {
      document.documentElement.classList.remove('dark');
      localStorage.theme = 'light';
      setIsDark(false);
    } else {
      document.documentElement.classList.add('dark');
      localStorage.theme = 'dark';
      setIsDark(true);
    }
  };

  return (
    <button 
      onClick={toggleTheme}
      className="p-2.5 rounded-xl bg-slate-100 dark:bg-slate-800 text-slate-800 dark:text-slate-100 transition"
      aria-label="Toggle theme"
    >
      {isDark ? '☀️ Light Mode' : '🌙 Dark Mode'}
    </button>
  );
}

Key Takeaways

  • Prevent theme flickering by executing an inline theme detection script in <head>.
  • Persist preferences to localStorage.theme.

In Part 45, we enter Module 8 to master Transitions, Transforms & Animations!