Skip to content
Kolorvia
Design

Dark Mode Color Design: Why You Can't Just Invert

Flipping your palette produces a dark mode that is technically dark and practically unusable. Here is what actually changes in the dark — surfaces, saturation, elevation, and contrast — and how to design for it.

· · 4 min read

On this page

Why inversion fails

The naive dark mode — swap white for black, flip every color to its opposite lightness — fails for a reason that's worth understanding: light mode palettes encode a set of assumptions that stop being true in the dark. Shadows communicate elevation; saturated brand colors sit comfortably on white; pure black text is the contrast king. Invert the canvas and every one of those assumptions breaks in its own way. Good dark modes aren't inverted — they're redesigned under different physics.

Don't use pure black

Almost every mature dark theme uses very dark gray, not #000000 — Material Design's famous baseline is #121212. The reasons are practical. Pure white text on pure black is the maximum possible contrast (21:1), and at typical body-text sizes that extreme causes a visual smearing effect — halation — that many users, particularly those with astigmatism, find genuinely harder to read than slightly softened contrast. Near-black also leaves headroom below your surfaces: if the base is #121212, hover states and pressed states can go darker; from #000000 there's nowhere to go. And dimmed text colors that read fine on dark gray tend to vanish on true black.

The same restraint applies to text: prefer near-white (around #e5e5e5#f5f5f5) over #ffffff for body copy, reserving pure white for small high-emphasis moments.

Elevation: light replaces shadow

On white, hierarchy comes from shadows — a card floats because it casts one. On a dark canvas shadows are nearly invisible, so elevation flips its encoding: higher surfaces get lighter. A modal sits on a lighter gray than the card below it, which is lighter than the page background. Practically, that means dark mode needs a ladder of dark grays — something like #0a0a0a → #171717 → #262626 → #404040 (the dark end of the neutral scale in our color chart) — where light mode got away with white plus shadows. If your dark UI looks flat, this is almost always what's missing.

Desaturate what sits on dark

Fully saturated colors that look confident on white tend to "vibrate" against dark backgrounds — optically buzzy, with colored halos at the edges — and saturated darks (a 700-level brand blue, say) can fail contrast against a dark surface entirely. The standard move is to shift accent colors toward lighter, less saturated variants in dark mode: where light mode used your brand's 600, dark mode probably wants its 300 or 400 — a tint doing structural work. This is also the cleanest way to keep brand identity: hold the hue, move lightness and saturation. Generate your color's lighter variants with the palette generator and test each against your actual dark surfaces, not against black.

Contrast math doesn't get a night off

WCAG thresholds are identical in the dark: 4.5:1 for body text, 3:1 for large text and UI parts. Two traps are specific to dark mode. First, mid-gray secondary text that passed on white often fails on #171717 — check the real pairs in the contrast checker rather than porting the light-mode grays. Second, contrast that's technically passing can still be uncomfortable at the extremes, per the halation problem above — dark mode is the one place where you're occasionally softening contrast on purpose, and that makes deliberate measurement more important, not less.

Images, and the details that give it away

Full-strength photography and illustration can glare against dark surfaces; many systems dim media slightly (90–95% opacity or a subtle dark overlay) so it sits in the page rather than punching through it. Semantic colors — success, warning, error — need the same lighter-variant treatment as brand accents, re-verified for contrast on dark. And borders often work better lighter than surfaces in dark mode (rgba(255 255 255 / 0.1)-style washes), where light mode used darker-than-surface lines.

Implementation notes that save rework

Respect the user's setting via the prefers-color-scheme media query, and design tokens semantically from day one: a token named surface or text-secondary can hold different values per scheme; a token named gray-100 cannot. If you're building the scale programmatically, do the lightness math in a perceptual space like OKLCH so "three steps lighter" looks like three even steps on both ends of the ladder. Then audit the dark theme as its own first-class deliverable — every pair, both schemes — because half of your users may see it more hours per day than the light one.

Related guides

Try it yourself

Put the theory into practice

Everything this guide explains is built into a free, live tool — try the math yourself.

We use cookies for site preferences and, where enabled, Google Analytics and Google AdSense — which may use cookies to personalize ads based on your visits here and elsewhere. See our Privacy Policy for details. Your color tool inputs are never sent to us regardless of your choice.