1.4.3 Contrast (Minimum)
WCAG 2.2 · 1.4.3 AA Perceivable
What it requires
The visual presentation of text and images of text must have a contrast ratio of at least 4.5:1 against its background. There are three exceptions:
- Large text — at least 18 point, or 14 point bold (roughly 24 px, or 18.66 px bold) — needs only 3:1.
- Incidental text — inactive (disabled) controls, pure decoration, text that is not visible to anyone, or text that is part of a picture containing other significant visual content — has no contrast requirement.
- Logotypes — text that is part of a logo or brand name — has no requirement.
The ratio is measured from the relative luminance of the text colour and the background colour directly behind it, and ranges from 1:1 to 21:1.
Low text contrast is one of the most common and most felt barriers on the web. It affects:
- People with low vision, who may not perceive faint text at all.
- People with colour-vision deficiencies and reduced contrast sensitivity, including many older users as contrast sensitivity declines with age.
- Anyone reading in bright sunlight, on a dimmed or low-quality screen, or under glare — a situational barrier that reaches every user.
How to detect it
| Check | How | Catches |
|---|---|---|
| Automated scan | Run axe, Lighthouse, or WAVE on the page. | Most solid-colour text/background pairs — good first pass. |
| Manual sampling | Use a contrast checker / eyedropper on suspect text, especially text over gradients, images, or semi-transparent overlays. | Cases tools skip or can't sample reliably. |
| States & themes | Check hover, focus, visited, placeholder text, and every theme (light, dark, high contrast). | Pairs that pass in one state/theme but fail in another. |
| Large-text rule | Confirm anything tested at 3:1 truly meets the 18 pt / 14 pt-bold size. | Body text wrongly judged against the relaxed threshold. |
Automated tools catch a large share of failures but cannot judge text over imagery or confirm the size needed for the large-text exception, so pair them with manual checks.
How to fix it
- Identify each failing text/background pair from your audit.
- Adjust the foreground or background colour until the ratio reaches 4.5:1 (or 3:1 for qualifying large text) — usually darkening text or lightening its background.
- For text over images or gradients, add a solid or sufficiently opaque overlay, a text shadow, or a contained background plate so the effective ratio is met everywhere.
- Fix design tokens, not one-off pages, so the corrected pair applies site-wide and across every theme.
- Re-test all interactive states and themes after the change.
/* Body text: #595959 on #ffffff = 7:1 — passes AA (and AAA) */
.body-text { color: #595959; background: #ffffff; }
/* Large heading (24px+): #767676 on #ffffff = 4.54:1 — passes at 3:1 */
.lead { color: #767676; background: #ffffff; font-size: 1.5rem; }
Copy-paste tests
Automated coverage
The axe-core rule color-contrast flags failures of this criterion.
Run it via the axe DevTools browser extension or axe-core in CI. Automated tools
only catch some failures — they can't judge text over images or confirm
the large-text size exception.
Run this in the browser console
// Read-only: lists text whose colour is faint relative to its background.
const lum = c => {
const [r, g, b] = c.match(/\d+/g).map(n => {
n /= 255; return n <= 0.03928 ? n / 12.92 : ((n + 0.055) / 1.055) ** 2.4;
});
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
};
const rows = [];
document.querySelectorAll('body *').forEach(el => {
if (!el.textContent.trim() || el.children.length) return;
const s = getComputedStyle(el);
const fg = lum(s.color), bg = lum(s.backgroundColor || 'rgb(255,255,255)');
const ratio = (Math.max(fg, bg) + 0.05) / (Math.min(fg, bg) + 0.05);
if (ratio < 4.5) { el.style.outline = '2px solid red'; rows.push({ el, ratio: ratio.toFixed(2), text: el.textContent.slice(0, 40) }); }
});
console.table(rows);
What to check manually: the script reads only the element's own background, so verify text sitting over images, gradients, or semi-transparent overlays with an eyedropper, and confirm any pair tested at 3:1 truly meets the 18 pt / 14 pt-bold large-text size.
Related
- WCAG 2.2 criteria index — all success criteria.
- Learn catalog — every lesson, tagged by criteria.
- Colour & contrast lesson — meeting the 1.4.x contrast thresholds in real markup.