Updated July 11, 2026

Dark Mode Is Not Inversion

The fastest dark mode ever shipped is one line of CSS: filter: invert(1) hue-rotate(180deg) on the root element. A team under deadline tries it, and the first screenshot looks almost plausible — light surfaces have gone dark, dark text has gone light, the layout is intact. Then someone uses it. Photos render as negatives until each one is counter-inverted. The brand blue comes back a queasy approximation of itself. Borders that used to read as quiet inset lines now look embossed, resting buttons look pressed, and nothing anyone can point to is exactly broken — the whole screen is just subtly, uniformly wrong.

Dark mode is not the light theme inverted — it is a second palette derived from the same seeds. Inversion reuses the light theme’s values in mirrored positions and fails three ways at once: role relationships flip wholesale, elevation loses its signal, and color drains on the dark ground. Derivation instead re-runs the palette’s construction for a dark context — its own lightness curve rising from a deep floor, chroma boosted to counter perceptual muting, and every role re-checked for contrast. That distinction underpins everything in our dark mode guide; this article is about why the obvious approach fails and what the working one does instead.

Why does inverting the light palette fail?

Inversion comes in two grades. The crude grade is the CSS filter: inverting RGB channels turns every color into its complement, which is why the hack needs a hue-rotate(180deg) chaser — and even then hues come back only approximately, and every image needs rescuing. The disciplined grade keeps hue and chroma and mirrors only lightness, and it is worth taking seriously, because it fails for reasons that teach.

Role logic breaks. In a light theme, a subtle border sits slightly darker than the surface it edges, and the eye reads that as a drawn line — an inset. Mirror the lightness and the border is now slightly lighter than its surface, which reads as embossed: a ridge catching light instead of a groove holding shadow. Multiply that across every intermediate relationship — dividers, table stripes, input strokes, hover tints, disabled text — and the theme fills with small physical lies. The deeper problem is that some relationships should flip (dark text on light rightly becomes light text on dark) while others must not, and inversion cannot tell the difference. It flips all of them, indiscriminately.

Elevation flips wrong. Light mode signals a raised surface with a shadow beneath it. On a dark ground that signal barely registers — there is almost nowhere darker for a shadow to go — so dark themes signal height the other way: surfaces get lighter as they rise, the convention codified in Material’s dark theme guidance. Inversion does nothing to produce this. The shadows survive the mirror, pointlessly, and the surface relationships land wherever the arithmetic puts them rather than where dark mode’s elevation logic needs them.

Color drains. Perceived colorfulness is judged relative to surroundings, and the same chroma value reads noticeably duller against near-black than against white. An inverted palette carries the light theme’s chroma values across unchanged, so the brand color arrives washed out, and every badge and accent arrives tired with it. Derived dark palettes counter this by boosting chroma — in Scale Composer by roughly 20 % — where inversion doesn’t know anything needs countering.

What does deriving a dark palette mean?

Derivation keeps the inputs and redoes the construction. The seeds — the brand colors the palette grew from — stay the same, so the dark theme is recognizably the same brand. Everything downstream is computed fresh for the dark context.

The lightness curve is the biggest change. A light-mode ramp runs from near white down to a deep step — L ≈ 0.97 to ≈ 0.25 — because light interfaces need many usable tints and a modest dark end. The derived dark ramp does not mirror that. It runs its own curve, re-ascending from a deep floor: the background-class steps sit around L ≈ 0.13–0.19, and the ramp climbs to ≈ 0.95 at the text-class end. Chroma is re-planned on top — boosted about 20 % against the light values, bounded by what the gamut allows at each lightness. And the semantic roles are re-derived rather than re-pointed: text, border and state roles are picked against the new surfaces, with the WCAG floors and APCA checked on the dark ground, because a pairing that passed on white proves nothing about near-black. The token export then carries the light and dark role sets side by side — a semantic and a semantic-dark section — so a theme switch swaps resolved values with no recomputation at runtime.

Where do inversion and derivation disagree in numbers?

Take the blue ramp seeded from #2563eboklch(0.546 0.215 262.9). The left column is the generated light ramp; the middle is the disciplined mirror (L → 1 − L, chroma kept); the right is the derived dark ramp.

Ramp positionLight LInverted LDerived dark L
background-class (50)0.970.03≈0.15
tint (300)0.800.20≈0.33
interactive core (500)0.610.39≈0.54
deep (700)0.430.57≈0.74
text-class (900)0.250.75≈0.95

Read the two ends first. The light ramp spans 0.97 → 0.25, so its mirror spans 0.03 → 0.75 — a range built for a light theme, flipped, not a range built for a dark one. The inverted floor at L 0.03 sits well below the ≈ 0.13–0.18 zone where dark backgrounds work, in territory where halation and crushed detail live. And the inverted ceiling stops at 0.75: the step that should carry text renders as oklch(0.75 0.026 262.9)#A5AEBF, a dim gray-blue, where the derived ramp reaches ≈ 0.95 — ≈ #E6EFFF, an off-white that can actually do the job.

Then read the chroma at the working step. Inversion keeps C 0.192 and drops it to L 0.39: ≈ #0134A9, a dark, muted blue that was never chosen by anyone. The derived ramp puts the interactive core at L ≈ 0.54 with chroma boosted to ≈ 0.23: ≈ #1C5EF1, vivid on the dark ground the way the seed was vivid on white.

Open this comparison in Scale Composer — the same blue seed rendered twice, naive inversion beside the derived dark ramp, with the lightness curves plotted over each other so the mirror and the re-ascent are visible as shapes.

The same blue ramp shown as a naive inversion beside a properly derived dark palette, with their lightness curves overlaid

What still needs a designer?

Derivation automates the values, not the judgment. A few decisions stay human. Which elements keep full vividness is one: a dark theme where every fill takes the boosted chroma can read louder than its light counterpart, and deciding what stays quiet is a design call. Imagery is another — photographs and illustrations neither invert nor derive, and choosing a dark-appropriate treatment for them is its own task. And the page anchor — whether the darkest background stays tied to the brand’s deep step or decouples into a plain neutral — changes the whole theme’s temperature. The derivation gives you a correct starting palette; these choices make it a designed one.

Try it on your own palette

The difference between mirrored and derived is easier to feel than to read about. Derive a dark palette from your own brand color — paste a seed, and watch the dark ramp come out with its own curve, its boosted chroma and its re-checked roles, next to what an inversion would have given you.

Keep reading