Guide
Dark themes and the contrast mistakes they hide
Dark interfaces break the assumptions most color tools are built on, starting with which swatch is the page. What actually goes wrong, and how to check for it.
6 min read
Dark interfaces are not light interfaces with the colours swapped, and most colour tooling was built on assumptions that only hold in one direction. The result is a class of failure that is easy to ship and hard to notice: checks that pass, on pairings nobody will ever see.
Which swatch is the page?
Almost every palette tool answers this the same way — the lightest colour is the background, the darkest is the text. That is correct for a light UI and exactly backwards for a dark one.
Give such a tool six dark neutrals and a yellow accent and it will nominate the yellow as the page and the page as the body text, then confidently report the contrast ratio between two colours that never appear together. The palette scores well. The pairs actually on screen go unmeasured. That is the one failure mode a diagnostic tool cannot have, because it fails in the reassuring direction.
The subtler version of the same bug: a rule that treats any near-white in the palette as “obviously the page”. A dark theme ships its own near-white — it is the body text. So the one thing every genuine dark palette contains becomes the thing that disqualifies it from being recognised as dark. We shipped that bug ourselves; the fix was to decide polarity from where the neutrals cluster as a group, and to treat the extremes as evidence only when the opposite extreme is absent — since a palette holding both a near-white and a near-black holds them in either polarity.
Pure white text is a mistake
#FFFFFF on #000000 passes every automated check with the maximum possible ratio, and it is genuinely unpleasant to read. At high contrast on a dark field, light text blooms — strokes appear to spill past their edges, an effect that is worse on OLED, worse at large sizes, and worse for people with astigmatism.
This is the clearest case of a standard being a floor rather than a target. 4.5:1 is the minimum for body text; it does not follow that 21:1 is best. Softening the text toward a light grey and lifting the background off pure black is more readable while still comfortably passing.
Borders and shapes fail first
Contrast rules apply to more than text. Interactive boundaries — input outlines, focus rings, icon-only buttons, chart strokes — need 3:1 against their surroundings, and this is where dark themes break most often.
The reason is structural. In a light theme, surfaces are separated by shadow, which reads immediately. Shadow does not work on a dark background, so dark themes separate surfaces by lightness instead — a card slightly lighter than the page. Those steps are typically tiny, and a border at 1.4:1 against its surface simply is not there for a lot of people, while looking perfectly fine to whoever designed it on a good monitor.
Saturated colour behaves differently
A brand colour tuned to sit on white is usually too dark to sit on near-black — it needs to be lighter in the dark theme to hold the same ratio, and its chroma usually needs reducing too, because vivid colours on dark backgrounds read as vibrating rather than vivid.
The corollary is that a dark theme is not a colour transformation of a light one. Inverting lightness produces something that technically passes and looks wrong. The two themes share hues and role names; the values are derived separately for each.
What to check
- Body text against the page, and against every raised surface it sits on.
- Muted or secondary text — the first thing to fall below the line.
- Borders and dividers against both surfaces they separate.
- Focus rings, which are the one indicator some users navigate entirely by.
- Text on the primary button, measured rather than assumed to be white.
- Disabled states, which are meant to look inactive but still be legible.
The common thread: check the pairs that occur, not the palette’s extremes. A tool that picks the pairs for you has to get the theme’s direction right first, or every number after that is measuring the wrong thing.