Dark mode contrast: the WCAG ratios that hold up
The thresholds that apply, what changes when the background is near-black, and the measured ratios of a real dark palette.
Published: · Last reviewed:
Dark mode uses the same WCAG thresholds as everything else: 4.5:1 for body text, 3:1 for large text and for the parts of a control that identify it. But a near-black background makes them easy to pass and easy to overshoot, so the real work is deciding which elements are allowed maximum contrast.
The thresholds do not change
There is no separate dark-mode standard. The same numbers apply:
| What | Minimum ratio | Level |
|---|---|---|
| Body text | 4.5:1 | AA |
| Large text (18 pt, or 14 pt bold) | 3:1 | AA |
| UI component boundaries and graphics | 3:1 | AA |
| Body text | 7:1 | AAA |
| Large text | 4.5:1 | AAA |
"Large" in CSS terms is roughly 24 px, or 18.66 px when bold. The ratio itself
is (L1 + 0.05) / (L2 + 0.05), where L is relative luminance,
which is why the scale runs from 1:1 to a ceiling of 21:1, the ratio of pure
white to pure black.
Why dark mode flatters the numbers
Against a near-black background almost any legible foreground passes. A mid grey that would fail on white sails through on black. This is genuinely easier, and it is where dark themes go wrong, because passing is not the goal. If every element passes comfortably, nothing is dimmer than anything else, and the interface loses its hierarchy while scoring perfectly on the audit.
In dark mode, contrast is the hierarchy. Primary text near the top of the range, secondary text comfortably above 4.5:1, and non-essential metadata down near the floor, but only where losing it costs the user nothing.
Measured: a real dark palette
Ratios computed with the WCAG formula against #0a0811, the
background of this site. These are calculated, not estimated:
| Colour | Hex | Ratio on #0a0811 | Verdict |
|---|---|---|---|
| Cream, headings | #fffdf8 | 19.6:1 | Passes AAA |
| Ink, body text | #eceaf6 | 16.7:1 | Passes AAA |
| Light violet | #bca3ff | 9.3:1 | Passes AAA |
| Grey, secondary text | #9b95ae | 6.9:1 | Passes AA, not AAA |
| Violet, links | #9670ff | 5.7:1 | Passes AA, not AAA |
| Deep violet | #8b64f7 | 5.0:1 | Passes AA |
| Dim grey, metadata | #6d6684 | 3.7:1 | Large text only |
| Hairline border | #241f36 | 1.3:1 | Decorative only |
Two of those rows are worth reading as warnings rather than results. The dim grey at 3.7:1 is below the body-text threshold: it is fine for a decorative timestamp and wrong for anything a reader needs, and if you use a colour like it for small text you are making a trade, not passing a test. The hairline at 1.3:1 is nowhere near 3:1, which is correct for a divider: 3:1 applies to boundaries that identify a control, not to every line on the screen. Get that distinction wrong and you end up with an interface full of glowing borders in the name of accessibility.
We ran these numbers on our own palette while building My Larp Wallet, and adjusted two colours because of them. The calculation takes a minute and is worth doing on any palette before it is committed to a design system.
Do not put pure white on pure black
21:1 is the maximum available ratio and it is not the target. Bright text on a true black background produces halation (letterforms appear to bleed outward), and the effect is worse for readers with astigmatism, which is a large share of the population. Long-form reading at maximum contrast is tiring in a way that a contrast checker cannot see.
The convention that emerged is an off-black surface and an off-white
foreground. Material Design's dark theme baseline is #121212,
which still gives 18.7:1 with white: an enormous margin, with the harshest
edge taken off. Our own background is a very dark violet rather than a grey,
for the same reason.
The trap: coloured backgrounds
This is where most dark themes actually fail, and the failure is on the bright elements rather than the dark ones. Every ratio below is measured:
| Combination | Ratio | Body text at 4.5:1 |
|---|---|---|
White on violet #9670ff | 3.5:1 | Fails |
| Near-black on the same violet | 5.5:1 | Passes |
| White on a saturated green | 2.2:1 | Fails badly |
| Black on the same green | 9.5:1 | Passes |
| White on a saturated red | 4.1:1 | Fails, narrowly |
The pattern: an accent colour bright enough to glow on a dark background is too light to carry white text. Primary buttons and status badges therefore take dark labels, which looks wrong for about a day and then looks correct permanently. The red row is the dangerous one: 4.1:1 is close enough to pass an eyeball check and it still fails. It is the same conclusion we reached measuring gain and loss badges in the anatomy of a wallet portfolio screen, from the opposite direction.
Elevation has to come from the surface
In a light theme, depth comes from shadow. In a dark theme a shadow lands on a background that is already almost black, so it does nothing, which is why dark interfaces that were designed light first look uniformly flat.
The convention that works is the opposite: the higher the surface, the lighter it is. A card sits a step above the background, a sheet a step above the card, a menu above that. Material Design formalises this as an overlay of white at increasing opacity per elevation level. Two constraints follow. Each step must be visible (an increment too small to perceive is wasted complexity), and the steps have to stop before the top surface competes with the text on it. Three or four levels is usually the whole budget.
Practical consequence for text tokens: your secondary grey has to clear 4.5:1 against the lightest surface it can land on, not the background. That is the ratio to record in the design system.
Opacity is not a colour
Dimming text with opacity or an alpha channel does not change what
the checker needs to see. The ratio depends on the composited result: white at
60 % over a dark background is a specific grey, and that grey is what must be
measured. Two consequences:
- Alpha text over a gradient or an image has a different ratio at every point. It must pass at the lightest and the darkest.
- Stacked translucent surfaces (a sheet over a card over the background) shift the effective background under the text, so the same token can pass in one context and fail in another.
Where a value is fixed, resolve it to a hex colour once and use that. Alpha is for effects that genuinely need to composite, not for making a palette smaller.
A checklist that catches most of it
- Background off-black, not
#000000. - Body text at 4.5:1 or better against the surface it actually sits on.
- Coloured buttons and badges: dark label, not white.
- Anything below 4.5:1 must be genuinely optional to read.
- Focus rings and control boundaries at 3:1; dividers exempt.
- Never signal state with colour alone: pair it with a glyph or a word.
- Check the palette on a phone at minimum brightness, outdoors. It is the condition your design will most often be read in, and no automated tool simulates it.
Questions
Do dark mode designs use different contrast thresholds?
No. The same WCAG thresholds apply: 4.5:1 for body text, 3:1 for large text and for the parts of a control that identify it.
So what makes dark mode harder?
A near-black background makes those thresholds easy to pass and easy to overshoot. The real work is deciding which elements are allowed maximum contrast, not reaching it.
Compose the screen instead of describing it
Your tokens, your amounts, your accent, laid out in the browser, then opened on your phone at your own address. A mockup, and we never pretend otherwise.
- Unlimited tokens, amounts and accents
- Add it to your home screen; it opens like an app
- Live market prices that keep moving
- Your own address, mylarpwallet.com/you
Cancel anytime · Secure payment by Stripe · See the wallet
Keep reading
- For crypto wallet app builders: screens before launchThe pitch, the concept test and the design review; not the store listing.
- Guide: Anatomy of a crypto wallet portfolio screenCard widths, radii, vertical rhythm, and the one-pixel hairline that makes cards read as raised.
- Where a wallet simulator earns its place in a product teamNot the screenshots. The five places a composed screen saves a team actual time are the ones nobody lists, because they are…
- Crypto token icons: sizes, shapes and the trapsWhat size to draw them, why the circle is not really negotiable, and the four things that break a token icon on a dark…
- iPhone screen sizes in points and pixels: the full tableLayout happens in points, files are measured in pixels, and the bridge between them is a single multiplication. Every…