Accessibility

WCAG Contrast Ratios Explained: A Designer's Practical Guide

By the colorPaletteFinder Team9 min read

Here is a number I keep coming back to: in the 2025 WebAIM Million report, low-contrast text was the single most common accessibility failure on the web, present on 79.1% of the top one million home pages. Not missing alt text. Not unlabeled buttons. Contrast. The most-detected accessibility problem in the world is two colors that are too similar, and almost every team that ships it has no idea they did.

I have shipped that bug myself. Years ago I built a "premium" dashboard with elegant #9CA3AF gray text on white, signed off by everyone in the room because it looked refined on a brand-new Retina display in a dark conference room. A support ticket arrived a week later from a user on a sun-lit train who literally could not read the labels. The text was at roughly 2.6:1. WCAG asks for 4.5:1. That gap is the whole subject of this article.

What a WCAG contrast ratio actually is

A WCAG contrast ratio is a single number that describes how different two colors are in lightness, expressed as a ratio from 1:1 to 21:1. White on white is 1:1 (invisible). Pure black on pure white is 21:1 (the maximum). Everything you design lives somewhere in between, and WCAG sets the floor you are not allowed to drop below.

The crucial thing to internalize early: contrast is about luminance, not about whether colors "look different." Red and green look wildly different to most people, but a saturated red (#FF0000) on a saturated green (#008000) sits at only about 1.3:1 because they carry nearly the same lightness. To a person with red-green color blindness, or anyone glancing at a low-quality screen, that pairing is mush. Your eye is fooled by hue; the contrast formula is not.

The formula, in plain terms

The ratio is computed as (L1 + 0.05) / (L2 + 0.05), where L1 is the relative luminance of the lighter color and L2 is the luminance of the darker one. You will almost never compute this by hand, but understanding the two stages tells you why your instincts mislead you.

First, each color's relative luminance is found by taking its red, green and blue channels, "linearizing" them (undoing the gamma curve that screens apply, using the rule that channels at or below 0.03928 are divided by 12.92, and higher ones are run through ((c + 0.055) / 1.055) ^ 2.4), and then weighting them: 0.2126 for red, 0.7152 for green, and 0.0722 for blue. Those weights are not arbitrary. Human eyes are extraordinarily sensitive to green and nearly blind to blue by comparison.

This is the single most useful takeaway from the math: green carries roughly ten times the perceived brightness of blue. That is why pure blue text on black is painful and barely passes, while the same "darkness" of green reads fine. It is why your blue links on a dark background feel weak no matter how saturated you make them. If you only remember one thing about the formula, remember the weights.

The + 0.05 in the ratio is a constant that models ambient light reflecting off the screen, so even theoretically perfect blacks never produce an infinite ratio. It is the reason contrast ratios top out at 21:1.

The three thresholds you have to know

WCAG (the Web Content Accessibility Guidelines, maintained by the W3C) defines a small set of numbers. Memorize these and you have covered the vast majority of real work.

Notice the pattern: each level is roughly the next one up. Large-AA and non-text share 3:1; normal-AA and large-AAA share 4.5:1. It is less to remember than it looks.

AA vs AAA: which do you actually owe?

AA is the real-world standard. It is what the European Accessibility Act, the ADA-driven settlements in the US, Section 508, and essentially every procurement contract reference. When a lawyer or auditor says "WCAG compliant," they mean AA. AAA is the gold tier, and the guidelines themselves explicitly say AAA conformance is not required as a general policy for entire sites, partly because some content simply cannot reach 7:1 without looking broken.

My honest take after years of this: design body text to clear AA comfortably, then treat AAA as a target you hit for the content that matters most — the main reading column of an article, error messages, anything a stressed or low-vision user must parse under pressure. Chasing 7:1 on every caption and disabled label is a losing battle that flattens your whole palette into black-on-white.

Normal text vs large text — and the trap inside it

WCAG lets large text off easier (3:1 instead of 4.5:1) because bigger, heavier letterforms are legible at lower contrast. But the definition of "large" is specific and people get it wrong constantly.

The conversion that trips everyone is 1pt = 1.333px, which is why 18pt becomes 24px and 14pt becomes ~18.5px. So a 19px regular heading is not large text by WCAG's definition — it still owes the full 4.5:1. A 16px bold label is also not large. I have watched designs "pass" in someone's head because the heading "looked big," when in pixels it sat just under the threshold and needed the stricter ratio. When in doubt, hold body and subheadings to 4.5:1 and only claim the 3:1 break for genuinely large display type.

Non-text contrast: the criterion everyone forgets (1.4.11)

Here is where most otherwise-careful teams fail. WCAG 2.1 added Success Criterion 1.4.11, Non-text Contrast, requiring 3:1 for two categories that have nothing to do with reading:

The classic violation: a search field that is just a #FFFFFF box with a #E5E7EB light-gray 1px border on a white page. That border is about 1.2:1. Sighted users with low vision literally cannot find where to click. Pale placeholder text and ghost-button outlines fail the same way. Pure decoration is exempt, and so is text inside the component (that lives under 1.4.3 instead) — but the thing that signals "this is interactive" must reach 3:1 against whatever sits next to it.

How to measure it — and how to fix it

You do not eyeball contrast. You measure it. My everyday workflow:

When something fails, resist the urge to nudge the hue. Changing saturation barely moves contrast; changing lightness moves it a lot. Concretely:

The mistakes I see on real teams

A word on the future: WCAG 3 is exploring a perceptual model called APCA that judges contrast more like the human eye does, accounting for text size and weight together rather than a flat ratio. It is promising and worth watching, but as of today the ratios in this article — backed by W3C's Understanding 1.4.3 — are what gets you legally and practically compliant. Build to them, leave yourself a margin, and measure instead of guessing. The 79.1% of sites that fail mostly failed because nobody checked. Checking is the entire job.

Frequently Asked Questions

What is the minimum WCAG contrast ratio for normal text?

Normal body text needs a contrast ratio of at least 4.5:1 against its background to meet WCAG Level AA, which is the standard most laws and contracts reference. Large text (18pt/24px regular, or 14pt/~18.5px bold) only needs 3:1. The stricter AAA tier raises normal text to 7:1 and large text to 4.5:1.

What is the difference between WCAG AA and AAA contrast?

AA is the practical, legally-referenced standard: 4.5:1 for normal text and 3:1 for large text. AAA is the enhanced tier for users with low vision: 7:1 for normal text and 4.5:1 for large. The W3C does not require AAA across an entire site, so most teams build body text to AA with headroom and reserve AAA for the most critical reading content.

What counts as large text under WCAG?

Large text is 18pt and larger (24px) at normal weight, or 14pt and larger (about 18.5px) if bold. The conversion is 1pt = 1.333px. A common mistake is assuming a heading that merely looks big qualifies — a 19px or 20px regular heading is still below 24px and must meet the full 4.5:1 for normal text.

Does WCAG require contrast for buttons and icons, not just text?

Yes. Success Criterion 1.4.11 (Non-text Contrast), added in WCAG 2.1, requires a 3:1 ratio for UI component boundaries that indicate state — input borders, focus rings, checkbox outlines — and for graphical objects like icon shapes and chart elements needed to understand them. Pure decoration is exempt.

How do I fix text that fails the contrast check?

Adjust lightness, not hue or saturation — those barely move the ratio. Darken the foreground or lighten the background until you clear the threshold; for light text on a colored button it is usually fastest to deepen the background color. Measure the result with a contrast checker rather than eyeballing it, since hue differences fool the eye but not the luminance formula.

Want to experiment with colors?

Try our free color palette generator to find your perfect harmony — with a built-in WCAG contrast checker.

Open the Generator