You picked a text color for dark mode. It passes WCAG AA at 4.8:1. By every legal standard, it's accessible. But when you read a paragraph in dark mode, the text feels slightly blurry. The letters seem to bleed at the edges. After a few minutes, your eyes feel tired.
This isn't your imagination. It's not your monitor calibration. It's halation — a well-documented visual phenomenon that WCAG's contrast formula doesn't account for. And it's the reason why mathematically 'passing' dark mode text can still fail real users.
What Is Halation?
Halation is the perception that a bright area 'spreads' or 'blooms' into a surrounding dark area. Think of a streetlight at night — the light appears larger than the physical bulb, with a soft glow extending into the darkness. The same thing happens to white text on a black screen.
The mechanism is in your retina. When light hits the photoreceptors (rods and cones), adjacent receptors are also stimulated — a process called lateral inhibition. In the fovea (the center of your vision, where you read), bright-on-dark stimuli trigger more lateral spread than dark-on-bright stimuli. The result: white letters on black appear slightly thicker, fuzzier, and less defined than black letters on white.
This isn't a minor effect. Studies measuring visual acuity with different polarities consistently find that most people read dark-on-light text faster and with fewer errors than light-on-dark text, even when the contrast ratios are mathematically identical. The reason: halation degrades the effective contrast at letter boundaries.
Why WCAG Doesn't Catch This
The WCAG 2.x contrast formula is symmetric. The ratio formula (L1 + 0.05) / (L2 + 0.05) produces the same result whether the lighter color is in the numerator or denominator. White on black gives 21:1. Black on white gives 21:1. Mathematically, they're identical.
But your retina doesn't do math. It does biology. And the retinal response to light-on-dark is measurably different than dark-on-light at the same luminance difference.
This is the core limitation of the WCAG 2.x formula: it treats all contrast as luminance contrast, ignoring the perceptual asymmetry of polarity. It's a physics model, not a vision science model.
APCA Fixes This (Partially)
The APCA (Advanced Perceptual Contrast Algorithm) — the proposed replacement for WCAG 3.0 — addresses polarity asymmetry. APCA treats light-on-dark and dark-on-light as fundamentally different cases with different scoring curves. A color pair that scores 90 Lc in light mode might score only 75 Lc in dark mode — same colors, flipped polarity, different readability prediction.
This is why APCA scores are more reliable for dark mode contrast evaluation. Try our APCA Calculator — input your dark mode colors and compare the APCA score against the WCAG ratio. If WCAG says 5:1 but APCA says 65 Lc, trust APCA. It's accounting for halation; WCAG isn't.
Astigmatism and Dark Mode: A Double Penalty
Halation affects everyone to some degree. But for the roughly 33% of the population with astigmatism, dark mode text can be actively painful to read.
Astigmatism is an irregular curvature of the cornea or lens that prevents light from focusing evenly on the retina. The effect: point sources of light (like the strokes of white text) appear smeared or elongated along one axis. This smearing amplifies halation — the already-blurred boundaries of white letters become even more indistinct.
See if your dark mode text passes both WCAG and APCA. APCA accounts for polarity — it catches halation problems WCAG misses.
Check with APCAThis is the mechanism behind the common complaint: 'Dark mode gives me a headache.' It's not the brightness. It's not the color. It's the combination of halation (lateral spread of light in the retina) plus astigmatic smearing (optical distortion in the cornea) producing text that the visual system has to work harder to decode.
The extra cognitive effort — constantly re-resolving blurred letterforms — accumulates over minutes of reading. After a while, it manifests as eye strain, fatigue, and headache.
What Helps (And What Doesn't)
Thicker fonts help. Halation disproportionately affects thin strokes. A 300-weight font in dark mode is significantly harder to read than the same weight in light mode. Bumping to 500 or 600 weight in dark mode compensates for the blurred edges. If you can't change the color, change the weight.
Larger text helps. Above 24px (WCAG's 'large text' threshold), the ratio of letter area to boundary blur improves significantly. The halation spread is roughly constant in angular size — so larger letters have proportionally less blur. This is one reason WCAG allows 3:1 for large text even in dark mode.
Slightly off-white text helps more than you'd think. Pure white (#FFFFFF) creates the strongest halation because the luminance step is maximum. Dropping to #E5E7EB (15.8:1) reduces the luminance at the boundary while keeping contrast well above AAA. The difference in perceived sharpness is noticeable — try it yourself with our Dark Mode Contrast Checker.
Slightly off-black backgrounds help. Moving from #000000 to #121212 or #1E293B reduces the luminance gap between background and text, which reduces the lateral inhibition response. The background is still dark enough that text pops, but the boundary is gentler. Most modern dark mode designs use near-black for exactly this reason.
The Contrast Compensation Formula
How much extra contrast do you need in dark mode to match the perceived readability of light mode? Based on the research, here's a practical rule of thumb:
For body text (16px, 400 weight): Target 7:1 (AAA) in dark mode, not 4.5:1 (AA). The ~55% increase roughly compensates for halation-induced blur at small sizes.
For large text (24px+, or bold 19px+): Target 5:1 in dark mode, not 3:1 (AA). The size helps, but halation still eats into perceived contrast. 5:1 is achievable without making the text blindingly white.
For thin fonts (300 weight or lighter): Don't use thin fonts in dark mode. If you must, target 10:1 minimum — and test with real users. Thin strokes are the most vulnerable to halation blur.
For headings (bold, 28px+): 4.5:1 is sufficient. Large, bold letterforms have enough physical size and stroke weight that halation blur at the boundary doesn't affect recognition.
These aren't WCAG requirements — they're perceptual guidelines based on vision science. WCAG doesn't distinguish between polarities. Your users' retinas do.
Who Should Use Dark Mode (And Who Shouldn't)
Dark mode isn't universally better or worse. It depends on the user, the context, and the content.
Dark Mode Works Better For:
Light Mode Works Better For:
The takeaway: offer both. Don't choose for your users. prefers-color-scheme exists for a reason. Our Dark Mode Contrast Checker tests both polarities — verify every color pair in both modes before shipping.
The Bottom Line
Dark mode text feels harder to read because of halation — a real visual phenomenon that WCAG's symmetric formula doesn't capture. It's worse for people with astigmatism (~33% of the population) and for thin, small text. It's better for users with cataracts, in low light, and for large bold text.
The fix isn't to abandon dark mode. It's to compensate: target AAA (7:1+) instead of AA for body text, use slightly off-white instead of pure white, thicker fonts, and slightly larger sizes. And always provide a light mode option — because for a third of your users, dark mode isn't a preference, it's a penalty.
Test your dark mode palette with our APCA Calculator — it's the only free tool that accounts for polarity in contrast scoring. And run a full page audit with the Chrome Extension to catch every violation at once.