← All criteria

Perceivable · Level AA · 1.4.3

Contrast (Minimum)

Body text needs at least 4.5:1 contrast against its background. Large text — 18pt regular or 14pt bold and up, roughly 24px regular or 18.5px bold — gets a lower bar, 3:1, since bigger letterforms stay legible at lower contrast.

  • Low vision
  • Color blindness

How to recognize it

Pick out anything that reads as light gray on white, or a pastel color on a similarly light background — meta text, timestamps, placeholder-style labels, 'subtle' secondary copy — and run it through an actual contrast checker rather than eyeballing it. A very common real failure: a warning or accent-colored button (orange, light blue, mint) with white text on top, where the background itself is too light for white text to clear 4.5:1 even though it looks 'branded' and intentional. Another: text laid over a photo with a translucent overlay, where contrast depends on whatever happens to be behind it in that specific image, so it might pass over a dark patch of the photo and fail over a light one. Watch for the large-text exception being claimed incorrectly too — 16px bold text is not 'large text' under this criterion; the size threshold is specific and most body-sized bold text doesn't clear it.

How to fix it

Run every text/background color pair through a contrast checker and treat 4.5:1 as the real floor for normal text, reserving the 3:1 allowance for text that's actually large per the definition. Darken light grays rather than assuming a slightly muted color reads as 'accessible enough.' For colored buttons, check the specific text-on-background pair, not just whether the color matches the brand — a brand orange that works fine as an accent somewhere else can still fail once white text sits on top of it. For text over photos, use a solid or near-solid scrim (a dark overlay panel, not just a light gradient) behind the text so the contrast is fixed and verifiable once, instead of depending on whatever's in each individual photo.

Example

Avoid

p.meta {
  color: #999999; /* ~2.85:1 on white */
}
.btn-warning {
  background: #f0ad4e;
  color: #fff; /* ~1.95:1 — fails badly despite looking 'on-brand' */
}
.hero-overlay-text {
  color: #fff;
} /* sits directly on a photo with no scrim — contrast depends entirely on that image */

Prefer

p.meta {
  color: #595959; /* ~7:1 on white */
}
.btn-warning {
  background: #92400e;
  color: #fff; /* ~7.1:1 */
}
.hero-overlay {
  background: rgba(0, 0, 0, 0.55); /* solid scrim, contrast no longer depends on the photo */
}
.hero-overlay-text {
  color: #fff;
}

Resources