HandyBench

WCAG Color Contrast Checker

Test text vs. background contrast for accessibility.

Large text preview

The quick brown fox jumps over the lazy dog — normal body text at 14px.

14.68:1
Contrast ratio
✓ Pass
AA — normal text
✓ Pass
AA — large text
✓ Pass
AAA — normal text
✓ Pass
AAA — large text

How to use the WCAG Color Contrast Checker

  1. 1 Pick your text (foreground) color and background color.
  2. 2 Read the contrast ratio and the live preview.
  3. 3 Check the AA and AAA pass/fail badges for normal and large text.

How the contrast ratio is calculated

WCAG 2.x defines contrast through relative luminance. Each 8-bit RGB channel is divided by 255, then linearized: values at or below 0.03928 are divided by 12.92, and larger values become ((c + 0.055) / 1.055)2.4. Luminance is the weighted sum L = 0.2126 R + 0.7152 G + 0.0722 B, which reflects how much more sensitive the eye is to green than to blue. The ratio is then (L1 + 0.05) / (L2 + 0.05), with L1 the lighter color. It ranges from 1:1 (identical colors) to 21:1 (black on white). The checker accepts 3- or 6-digit hex values and works out the ratio live.

WCAG thresholds

LevelNormal textLarge text
AA4.5:13:1
AAA7:14.5:1

Large text means 18 pt (24 px) or bigger, or 14 pt (about 18.66 px) or bigger in bold. WCAG also asks for 3:1 on user-interface components such as input borders and icons that carry meaning (criterion 1.4.11), though this tool reports only the four text results.

Worked examples

These ratios were verified with the same formula the tool uses:

  • #1f2937 on white: L = 0.0215 against 1.0, so (1.05) / (0.0715) = 14.68:1. It passes everything, including AAA.
  • #767676 on white: 4.54:1, the lightest neutral gray that still passes AA for body text.
  • #777777 on white: 4.48:1. One hex step lighter, and it fails AA for normal text.
  • White on #3b82f6, a popular bright blue: 3.68:1. It fails AA for normal button text but passes for large text.
  • White on #2563eb, a darker blue: 5.17:1. It passes AA for normal text.

Common mistakes and edge cases

  • Rounding up. The tool shows up to two decimals, but the 4.5 threshold is exact. A true 4.497 displays as 4.5 yet is still a failure, so check the badge, not just the number.
  • Placeholder and disabled text. Placeholders are still text and must meet 4.5:1. Inactive controls are exempt, but a placeholder that vanishes into a field is a common complaint.
  • Text over images or gradients. The checker compares two flat colors. For a gradient, test the text against the worst-case point behind it.
  • Color alone. Contrast does not replace non-color cues. A red error and a green success of equal luminance look identical to many color-blind users.
  • Dark mode. Check both themes; a gray that passes on white often fails on dark stone.

To find replacement colors, build options with the color palette generator and convert between formats with the color converter.

Examples

  • ▸ Confirming body text meets the 4.5:1 minimum for WCAG AA.
  • ▸ Checking whether a button label is readable on a brand-color background.

Frequently asked questions

What contrast ratio do I need?

WCAG AA requires at least 4.5:1 for normal text and 3:1 for large text (18pt, or 14pt bold). AAA is stricter: 7:1 for normal text and 4.5:1 for large text.

What counts as “large text”?

Large text is roughly 18pt (24px) and up, or 14pt (about 18.66px) and up when bold. Larger glyphs are legible at lower contrast, so the thresholds are relaxed.

How is the ratio calculated?

It uses the WCAG relative luminance formula: (L1 + 0.05) / (L2 + 0.05), where L1 and L2 are the lighter and darker colors’ luminance. Ratios range from 1:1 to 21:1.

Does white text on a brand-blue button pass WCAG?

It depends on the blue. White on #3b82f6 is only 3.68:1, which fails AA for normal text, while white on the darker #2563eb is 5.17:1 and passes. Darkening the background a step or two usually fixes a failing button.

What is the lightest gray I can use for body text on white?

#767676 on white is 4.54:1, the lightest neutral gray that passes AA for normal text. #777777 drops to 4.48:1 and fails, so the threshold falls between two adjacent hex values.