Dark mode in ~15 lines, no library — and the part most tutorials skip: no white flash on load. Here's the whole pattern.
1. Colors as variables
:root{ --bg:#ffffff; --text:#1a1a1a }
[data-theme="dark"]{ --bg:#0e1116; --text:#e8ecf3 }
body{ background:var(--bg); color:var(--text) }
Never hard-code colors. Reference variables everywhere, and switching theme becomes one attribute change.
2. The toggle
const root = document.documentElement;
const next = root.getAttribute('data-theme')==='dark' ? 'light':'dark';
root.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
3. Kill the flash (the bit everyone forgets)
Apply the saved theme before first paint with a tiny inline script at the top of your , before the stylesheet:
const saved = localStorage.getItem('theme');
const dark = matchMedia('(prefers-color-scheme: dark)').matches;
document.documentElement.setAttribute('data-theme', saved || (dark?'dark':'light'));
That's what removes the jarring white flash on reload. Bonus: add color-scheme: light dark so form controls and scrollbars adapt too.
Want theming done right out of the box? Every DesignToCodes template that supports dark mode uses this exact approach.
Library or hand-rolled — how do you ship dark mode? 👇
Top comments (0)