When chromatic accessibility comes up, the immediate reflex is to open a contrast checker. 4.5:1 for regular text, 3:1 for large text — box ticked, move on. Except that ratio only tells part of the story.
WCAG measures the difference in relative luminance between two colours. The human eye, however, interprets much more: optical vibration between two saturated hues, the confusion induced by colour blindness, the fatigue caused by a background that "jumps" visually. A colour combination can pass every test and still be unpleasant to look at for more than three seconds.
This article covers both dimensions — the measurable and the perceptual — to give you a complete picture of what works, and why.
What WCAG measures (and why it's necessary but not sufficient)
The WCAG 2.1 standard defines three contrast levels for text:
Level AA (minimum): 4.5:1 for normal text, 3:1 for large text (18pt+ or 14pt+ bold)
Level AAA (enhanced): 7:1 for normal text, 4.5:1 for large text
UI components and graphics: 3:1 minimum (buttons, informative icons, meaningful borders)
The calculation is based on relative luminance — a value between 0 (absolute black) and 1 (pure white) that accounts for the non-linearity of human brightness perception. The ratio (L1 + 0.05) / (L2 + 0.05) yields a number between 1:1 (no contrast) and 21:1 (black on white).
This model is robust for measuring basic legibility. But it doesn't account for:
Chromatic confusion: two colours that are very different in hue can have nearly identical luminance for a colour-blind user.
Optical vibration (chromostereopsis): certain pairs of saturated colours create an illusion of movement or depth that exhausts the eyes.
Size and context: small white text on a dark purple background can technically pass AA while remaining painful to read on a low-resolution screen.
Combinations to avoid
Red + green
The worst mistake in interface design. Around 8% of men and 0.5% of women have deuteranomaly or protanomaly — the two most common forms of colour blindness, which affect precisely the perception of red and green. For these users, the two colours can appear identical or nearly indistinguishable.
The concrete problem: using red exclusively for errors and green for successes, with no accompanying icon or text. This is one of the most documented anti-patterns in digital accessibility.
The rule: colour must never be the sole carrier of information. Always pair it with an icon, a label, a pattern, or a typographic style.
Light grey on white (and any pale-on-pale combination)
One of the most common flaws in today's "minimalist" interfaces. Text at #9CA3AF on a #FFFFFF background gives a ratio of around 2.5:1 — well below the AA minimum. Yet this combination is ubiquitous in modern UI kits, frequently used for placeholders, secondary labels, and help text.
The problem worsens with age (contrast sensitivity naturally declines), eye strain, a low-quality screen, or a bright environment.
The threshold to remember: if you can't read the text while squinting slightly, it probably doesn't pass AA.
Bright yellow on white
#FFFF00 on #FFFFFF is visually aggressive and yet the contrast is catastrophic (1.07:1). This is the trap of "vivid" colours: high saturation doesn't compensate for a luminance close to that of the background. Pure yellow is one of the most luminous colours in the visible spectrum — placing it on white makes it nearly invisible.
Blue + red (and saturated "primary" pairs)
The blue channel is poorly served by the human retina: S-cones (sensitive to blue) are fewer in number than M and L cones, and their spatial resolution is lower. Pure blue text on a red background — or the reverse — produces a "chromatic blur" and vibration effect that makes reading physically uncomfortable.
More broadly, any pair of complementary colours at maximum saturation (blue/orange, purple/yellow, green/magenta) triggers a phenomenon called chromostereopsis: the brain attempts to "focus" on two different wavelengths simultaneously, creating an illusion of depth or trembling. The result: eye strain, and sometimes headaches.
Penn State Accessibility sums it up well: "Vibrating color combinations should be avoided because they can cause headaches and make content virtually unreadable."
Combinations that work
Very dark text on very light background (and vice versa)
The canonical combination. Pure black #000000 on pure white #FFFFFF gives 21:1 — the theoretical maximum. In practice, most design systems prefer to soften slightly:
Text
#1A1A1Aon background#FAFAFA→ ratio ~19:1, less fatigue for extended readingText
#0B0F1Fon background#FDFDFD→ same effect, slight cool tint
This works for everyone: colour-blind users, low-vision users, users on low-end screens.
Dark blue on white or cream
#003366 on #FFFFFF (ratio ~12:1) is the gold-standard trust choice. Banks, public services, medical interfaces: it's no coincidence. The blue hue doesn't interfere with red-green colour blindness, luminance is high, and the psychological connotation (reliability, professionalism) reinforces perceived legibility.
Well-calibrated dark mode
The temptation in dark mode is to go to extremes: background #000000, text #FFFFFF. That's a mistake. Pure white on absolute black creates halation — a glowing halo effect that makes reading fatiguing, particularly for users with astigmatism.
Current recommendations converge on:
Background: between
#0D0D0Dand#1A1A1APrimary text:
#E8E8E8or#EAEAEA— never pure whiteSecondary text: around
#9B9FAA
For data and charts
Monochromatic or sequential palettes (luminance variations on a single hue) are more robust than rainbow palettes. ColorBrewer, designed for scientific cartography, remains a solid reference: it offers palettes tested for colour blindness and greyscale printing.
General rule: never distinguish two categories by hue alone. Vary luminance, shape, and pattern as well.
What WCAG doesn't check yet
The current standard has a recognised limitation: it treats all text of the same size identically, even though legibility also depends on context, font weight, and the nature of the background.
APCA (Advanced Perceptual Contrast Algorithm) is the method proposed for WCAG 3.0. It calculates a "lightness contrast" that accounts for reading direction (dark text on light background vs light text on dark background), typeface, and weight. Results can diverge significantly from WCAG 2.1 in certain cases — particularly light text on deep coloured backgrounds.
For a tool like Frontend Studio, integrating both metrics simultaneously provides far more complete information than a single WCAG ratio.
Practical checklist
Before validating any colour combination:
WCAG
Ratio ≥ 4.5:1 for body text
Ratio ≥ 3:1 for UI components and large text
Tested with a verification tool (WebAIM Contrast Checker, Colour Contrast Analyser)
Colour blindness
The combination doesn't rely on red/green as the sole information carrier
Tested via a colour blindness simulator (Coblis, Sim Daltonism, DevTools)
Every piece of colour-coded information is paired with an icon, text, or shape
Perception
No complementary pairs at maximum saturation side by side (vibration)
In dark mode, background and text avoid pure black and pure white
Readable without effort on a mid-range screen, in a bright environment
Resources
WCAG 2.1 — Understanding Contrast (Minimum) — W3C
Colors and Luminance — MDN Web Docs
Vibrating Colors — Penn State Accessibility
ColorBrewer — accessible data palettes
APCA Contrast Calculator — future WCAG 3.0 standard