Skip to content

feat: eliminate theme flash on initial paint (FOUC) via inline script [FaaFyfxR9WAQrL7FcAgEHJvztd8cVMxvjHRS55rw1nwH] - #520

Open
waterWang wants to merge 1 commit into
BountyOnChain:mainfrom
waterWang:feat/eliminate-theme-fouc-389
Open

feat: eliminate theme flash on initial paint (FOUC) via inline script [FaaFyfxR9WAQrL7FcAgEHJvztd8cVMxvjHRS55rw1nwH]#520
waterWang wants to merge 1 commit into
BountyOnChain:mainfrom
waterWang:feat/eliminate-theme-fouc-389

Conversation

@waterWang

Copy link
Copy Markdown

Closes #389

Problem

ThemeProvider initialises useState<Theme>('dark') on the server. The client then reads localStorage/matchMedia inside useEffect. First paint is always dark, then snaps to the correct theme on hydration — causing a flash of incorrect theme (FOUC).

Changes

  1. New initializeTheme() export in components/ThemeProvider.tsx — a standalone function that reads the saved theme from localStorage (or falls back to prefers-color-scheme / "dark") and applies it to document.documentElement.

  2. Inline script in app/layout.tsx — a synchronous IIFE injected into the HTML <head> that runs before React hydrates. It reads the theme and sets the dark class + colorScheme style on <html> immediately, so the first paint always has the correct theme.

Acceptance Criteria

  • ✅ No flash of incorrect theme on initial page load
  • ✅ localStorage theme preference is respected
  • ✅ System prefers-color-scheme is respected as fallback
  • ✅ Script is wrapped in try/catch — safe even if localStorage is blocked
  • suppressHydrationWarning already present on <html>

… [FaaFyfxR9WAQrL7FcAgEHJvztd8cVMxvjHRS55rw1nwH]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[S-B] Eliminate theme flash on initial paint (FOUC)

1 participant