Diagnosing Chakra UI Color Mode Issues: SSR Flash, Hydration Mismatch, and Toggle Persistence
When Chakra UI pages flash or show hydration mismatches, the culprit is often the missing <code>ColorModeScript</code>, an incorrect theme config, or hard‑coded colors. This guide walks through symptoms, diagnostics, fixes, and escalation steps so you can get your dark‑mode toggle working reliably.
02 Feb 2026, 01:06 UTC

Recognizable Symptoms
When a Chakra UI powered page first loads, you may see a brief flash of the wrong theme—light mode snapping to dark or vice‑versa. In React/Next.js you’ll also notice a console warning: Warning: React does not recognize the className prop on a DOM element. or a hydration mismatch error. The toggle button sometimes appears to work, but the choice does not persist after a full page reload.
Primary Causes
- Missing or misplaced
ColorModeScript: The script that injects the initialdata-themeattribute runs before hydration. If it’s omitted or placed after the app content, the server and client render different modes. - Incorrect theme configuration: Chakra expects a config object with
initialColorModeanduseSystemColorModekeys. A typo or missing key silently falls back to defaults. - Hard‑coded color values: Using literal strings like
bg="white"bypasses the color mode system. The toggle changes thedata-themeattribute, but the component never reacts.
Ordered Checks
- Verify
ColorModeScriptplacementIn
pages/_app.tsx(orapp/layout.tsxfor Next 13), ensure the script is rendered once, beforeChakraProviderand the rest of the app:import { ChakraProvider, ColorModeScript } from "@chakra-ui/react"; import theme from "../theme"; export default function App({ Component, pageProps }) { return ( <> ); }Run
npm run devand inspect the generatedindex.htmlto confirm thedata-themeattribute appears on thehtmltag before any component markup. - Check the theme config
Open
theme.tsand confirm the keys are correct. For Chakra v3 you should useconfiginsideextendTheme:import { extendTheme, ThemeConfig } from "@chakra-ui/react"; const config: ThemeConfig = { initialColorMode: "light", // "dark" or "system" useSystemColorMode: true, }; export default extendTheme({ config });Run
npm list @chakra-ui/reactto confirm the major version matches the syntax you’re using. - Inspect storage of the color mode
Chakra writes the chosen mode to
localStorageon the client, but for server‑side rendering it reads a cookie namedchakra-ui-color-mode. Ensure your application writes to this cookie (e.g., viadocument.cookie = "chakra-ui-color-mode=dark; path=/") rather than only relying onlocalStorage. If you’re using a framework that strips cookies on the first request, the server will default to theinitialColorModevalue. - Search for hard‑coded colors
Run:
grep -R "bg=\"white\"" src/ | wc -lReplace any literal values with semantic tokens or
useColorModeValue:import { useColorModeValue } from "@chakra-ui/react"; const bg = useColorModeValue("white", "gray.800"); … - Disable system mode for testing
Set
useSystemColorMode: falseand reload. If the flash disappears, the issue is related to detecting the OS preference. Some browsers cache theprefers-color-schememedia query, so clear the cache or test in incognito mode.
Fixes Tied to Findings
- Missing
ColorModeScript: Add it as shown in the first check. If you’re using Next 13’sappdirectory, place it inapp/layout.tsxbefore the provider. - Incorrect config keys: Correct the key names and ensure the config object is passed to
extendTheme. For Chakra v2 the keys are the same, but theextendThemesignature differs. - Hard‑coded colors: Refactor components to use semantic tokens or
useColorModeValue. In Chakra v3 you can also definesemanticTokensfor colors that automatically switch. - Cookie vs. localStorage: Add a small helper to sync the chosen mode to a cookie before the first render. Example:
// In a custom hook or component that toggles the mode
useEffect(() => {
const mode = document.documentElement.dataset.theme;
document.cookie = `chakra-ui-color-mode=${mode}; path=/`;
}, []);
Escalation Criteria
If after performing all the above checks the issue persists, consider:
- SSR streaming or incremental rendering features in your framework that may delay
ColorModeScriptexecution. - Third‑party scripts that modify
document.documentElementor addclassattributes. - Browser‑specific quirks—test in Chrome, Firefox, Safari, and Edge. If the problem is isolated, file a reproducible sandbox on CodeSandbox and open an issue in the Chakra UI GitHub repo.
- Framework‑level bugs—consult the Next JS or Remix SSR documentation for known color‑mode interaction issues.
Practical Verification
- Hard‑reload the page (Ctrl+Shift+R) with the browser cache disabled. Watch the console for hydration warnings.
- View the source (
Ctrl+U) and verify thehtmltag containsdata-theme="light"(or the expected mode) before any component markup. - Toggle the theme using the UI button, then refresh. The mode should persist and the console should remain clean.
- Use the browser devtools to inspect the
data-themeattribute onhtmlbefore and after toggling.
Summary
Chakra UI’s color mode system relies on a small ColorModeScript that sets a data-theme attribute. When that script is missing, mis‑configured, or the theme config is wrong, the server and client render different modes, leading to flash and hydration errors. Hard‑coded colors bypass the system entirely. By following the ordered checks—verifying script placement, theme config, storage strategy, and component color usage—you can isolate and fix most color‑mode issues. If the problem remains, narrow it down to framework or browser quirks and consult the relevant issue trackers.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.