WCAG 1.4.3 · Level AA · WCAG 2.0
Contrast (Minimum)
Text must have a contrast ratio of at least 4.5:1 against its background. Large text (≥18pt or 14pt bold) may go as low as 3:1.
- Principle
- Perceivable
- Guideline
- Distinguishable
- Level
- AA
- Added in
- WCAG 2.0
What it really means
Text must have a contrast ratio of at least 4.5:1 against its background. Large text — which WCAG defines as at least 18pt (≈24px) or 14pt bold (≈19px bold) — may go as low as 3:1. Logos and pure decoration are exempt.
This is the single most-cited WCAG violation on the web. WebAIM's annual Million study finds low-contrast text on ~80% of the top one million home pages. Design teams pick greys that look elegant on a pristine 5K screen; users on a cheap laptop in a sunlit café can't read them.
Who it helps
- Low-vision users (cataracts, macular degeneration, astigmatism).
- Everyone in bright ambient light — sunlit café, train, outdoor kiosk.
- Everyone with a cheap or old screen.
- Everyone on "night mode", which crushes certain palettes.
How to test
- Use a contrast checker: WebAIM's Contrast Checker, Colour Contrast Analyser, or Chrome DevTools' built-in picker (click a colour swatch in Styles → Contrast ratio).
- Run axe DevTools — the
color-contrastrule catches most cases. It can't inspect text-over-image, gradients, or user-generated colours; review those by hand. - Test in the browser's forced-colors mode (Windows High Contrast or Firefox Contrast). Colours defined with CSS system colors survive; hard-coded hex values may invert poorly.
What counts as "large text"
- At least 18pt (24 CSS pixels) at any weight.
- Or at least 14pt (18.66 CSS pixels) if the font weight is 700+ (bold).
Everything else is "normal text" and must hit 4.5:1.
A failing pattern
/* Light grey on white — 3.1:1. Fails at any size. */
.muted-text {
color: #999;
background: #fff;
}
/* Brand blue on brand white — 3.9:1 at 16px. Fails body text. */
.cta {
color: #2563eb; /* blue-600 */
background: #ffffff;
}
/* Dark mode overlay where muted turned illegible. */
.dark .hint { color: #475569; background: #0f172a; } /* 2.8:1 — fails */A passing pattern
/* Slate-700 on white — 8.6:1. AAA at any size. */
.body-text {
color: #334155;
background: #ffffff;
}
/* Brand cyan-800 — 8.0:1 on #fafaf7. AAA normal text. */
.brand {
color: #155e75;
background: #fafaf7;
}
/* Paired with an icon, not just colour — belt and braces. */
.error {
color: #991b1b; /* 8.1:1 on white — AAA */
background: #ffffff;
}The strictest shade-picking strategy: pick your body colour first by
contrast target, then design the palette around it. Tailwind's 700–900
range on white (slate-700, zinc-800, neutral-900) all clear AAA.
Notes and edge cases
- Placeholder text is text.
::placeholder { color: #d1d5db }fails at 4.5:1 — bump it to#6b7280or darker. - Disabled controls are commonly exempt from contrast requirements per the WCAG "inactive UI component" exception, but users still need to read them. Shoot for at least 3:1 even when disabled.
- Text over images must meet contrast against the effective background. Use a scrim or gradient overlay if the image is busy.
Related rules
- axe: color-contrast — the automated check.
- axe: color-contrast-enhanced — AAA 7:1 variant.
- axe: link-in-text-block — inline links distinguishable without colour.
- WCAG 1.4.6 Contrast (Enhanced) — the AAA 7:1 bar above this one.
- WCAG 1.4.11 Non-text Contrast — companion rule for icons, borders, and graphics.