← All writing

Dark mode done right: contrast, depth and legibility

Good dark mode is not an inverted light theme. It is re-decided contrast, depth carried by surface lightness, and text tuned so it reads instead of glows.

The fastest way to get dark mode wrong is to invert the light theme and ship it. Flip white to black, black to white, and call it done. What you get looks like dark mode in a thumbnail and falls apart the moment someone reads it: text that vibrates, surfaces that all sit at the same flat depth, and accent colors that glow like a warning light. Good dark mode is not an inversion. It is a second set of decisions, made specifically for a dark surface, about three things: contrast, depth, and legibility.

This site runs a dark theme as its default, so I have had to make all three of those decisions in production rather than in theory. The navy background is not black, the text is not pure white, and the accent does not carry the whole page. Those are not accidents. They are the difference between a dark interface that reads and one that just looks moody in a screenshot.

Contrast has to be re-decided, not inverted

The first mistake is assuming contrast carries over from light mode. It does not. Pure white text on a pure black background is the maximum possible contrast, and it is too much: the letters vibrate against the void, the halation makes edges shimmer, and long reading becomes tiring in a way people feel without being able to name. The eye did not ask for maximum contrast. It asked for comfortable contrast.

So dark mode needs its own contrast pairs, chosen for a dark surface. The background moves off pure black to a very dark tone with a little color in it, which on this site is a deep navy rather than a flat black. The body text moves off pure white to a soft near-white, so it is clearly legible without buzzing. The pairs still have to clear the WCAG contrast minimums, which is the floor, but the goal above that floor is a contrast that is high enough to read easily and no higher than that. More is not better here. More is fatigue.

This is also where a common accessibility trap hides: teams check contrast in light mode, pass, and assume the dark theme inherits the result. It does not, because the values changed. Dark mode is a separate set of pairs and needs its own check.

Depth comes from lightness, not shadow

In light mode, elevation is easy: a drop shadow lifts a card off the page, because in the physical world things cast shadows onto lighter surfaces. In dark mode that intuition breaks. A shadow on a near-black surface is nearly invisible, because there is no lighter ground for it to fall on. Lean on shadows in dark mode and everything collapses onto one flat plane, which is why so many dark interfaces feel like a single sheet of the same color with text on it.

The fix is to carry depth with lightness instead. On a dark surface, things that are meant to feel closer are lighter, not shadowed. The base background is the darkest layer. A card sits on a slightly lighter surface. A raised element inside it is lighter still. On this site there is a small ladder of surface tones for exactly this, so the eye reads a hierarchy of nearer and farther by how light each layer is, the way it would read shadow depth in light mode. Shadows can still play a supporting role, softly, but lightness does the real structural work. Get this ladder right and a dark interface gains the depth that inversion strips out.

Legibility is about restraint

The third set of decisions is about keeping things readable, and most of it comes down to restraint.

Text wants tiers, not a single bright white. A small set of ink levels, a near-white for primary text and a dimmer tone for secondary, gives you hierarchy without turning down opacity so far that the secondary text fails contrast. There is a limit to this: dim text too far in the name of hierarchy and it stops being readable, so the dim tone still has to clear the contrast floor. Hierarchy is not a license to make some text hard to see.

Accent colors need a harder look in dark mode than anywhere else. A saturated color that looks crisp on white will often glow on a dark surface, buzzing at its edges and pulling the eye even when it is not the point. The answer is to desaturate slightly and to spend the accent carefully. On this site the orange marks primary actions and signature moments and nothing else, and a calmer support blue does the quieter work of wayfinding, precisely so the bright color never has to carry a whole screen. A dark interface where the accent is everywhere is a dark interface that never lets the eye rest.

And pure white surfaces, if any survive from light mode, have to go. A white panel dropped into a dark layout is a small flashbang: the pupil, adjusted for the dark surroundings, gets hit with the brightest possible value. Dark mode has no room for pure white blocks. Everything sits inside the dark range, at the lightness its depth calls for.

Questions I get about dark mode

Should every product offer dark mode? Not automatically. A dark theme is a second theme to design, test, and maintain, with its own contrast pairs and its own depth ladder. Offer it when it genuinely serves the reading context, not because it is expected, and if you offer it, commit to designing it properly rather than shipping an inversion.

Can I generate the dark palette from the light one? You can start there, but treat the output as a first draft to correct, not a finished theme. The background needs pulling off pure black, the text off pure white, the accents desaturating, and the depth rebuilding through lightness. Every one of those is a manual decision the generator will not make for you.

Is dark mode better for accessibility? It helps some people and hurts others; people with certain visual conditions read dark text on light better, and vice versa. That is the real argument for offering both and letting the reader choose, rather than declaring one universally correct.

The short version

Do not invert. Re-decide contrast for a dark surface, comfortable rather than maximum, and still above the floor. Carry depth with a ladder of surface lightness, because shadows have nothing to fall on. Keep text in legible tiers, desaturate and ration the accent so it reads instead of glows, and let no pure white block survive. Dark mode done right is a second set of deliberate decisions, and it is the difference between an interface that looks dark and one that is genuinely comfortable to read.

You can see all three decisions in one place on the design system this site runs on, dark values and all, and building coherent light and dark themes is part of my design systems architecture work.

ShareXLinkedIn
← PreviousConfig 2026: code just became a design materialNext →The handoff is dissolving. Good.

Keep reading