Blog

Dark mode without a flash

๐Ÿ“… July 30, 2026 โœ๏ธ Jonas Reiter Engineering

Why the theme has to be set before the first paint, what happens without JavaScript and how a generated mirror solves the problem.

A white flash when loading a dark page is the most common symptom of a theme applied too late. This is how we got rid of it.

Before the first paint

The theme attribute is set by a tiny inline script in the <head> โ€“ stored choice first, otherwise system preference. At that moment the browser has not drawn anything yet.

Without JavaScript

No script, no attribute. So that the page still turns dark, a prefers-color-scheme rule mirrors all dark tokens โ€“ but only while no attribute is set. With JavaScript the choice wins, without it the system does.

The mirror drifts

Hand-written mirrors go stale silently as soon as the foundation adds tokens. That is why ours is generated at build time from the installed foundation and checked against it in CI.

@media (prefers-color-scheme: dark) {
  :root:not([data-theme]) { /* generated */ }
}

The browser chrome color

theme-color exists twice, with a media attribute per scheme. On toggle the script sets both to the computed background โ€“ without a single hex value in the code.