W3docs

Color

Color Contrast Checker

Check the WCAG contrast ratio between two colors and see AA / AAA results for small and large text.

Color Contrast Checker

Ratio

8.6:1

Small sample text.

Large sample text.

WCAG AA
Small
Large
WCAG AAA
Small
Large

About the contrast ratio checker

This tool computes the WCAG contrast ratio between a background color and a foreground color and reports whether the pair passes WCAG AA and AAA for both small and large text. Type a 3- or 6-digit hex value (#00f or #0000ff) into the Background and Foreground fields — or use the native color-picker swatch next to each — and the preview box, the ratio, and four pass/fail badges update on every keystroke. Only hex is accepted here: the shared color parser this site’s other tools use can also read rgb(), hsl(), hwb(), cmyk(), and named colors like tomato, but this checker’s inputs are hex-only.

Everything runs client-side: a useMemo hook recomputes the ratio from the two color values on every change, with no network request involved. The math is the W3C’s own two-step formula, reimplemented from scratch rather than pulled from a library — a code comment notes it replaces tinycolor.readability() to keep the tool dependency-free. Each channel is gamma-corrected, the three channels are weighted 0.2126R + 0.7152G + 0.0722B into a relative luminance, and the ratio is (lighter + 0.05) / (darker + 0.05), a value from 1.0:1 (identical colors) to 21.0:1 (pure black on pure white).

Reach for this before shipping any UI decision that pairs text with a background: body copy, disabled-button labels, placeholder text, link colors on a colored card. WCAG AA (4.5:1 small text, 3:1 large text) is the bar most accessibility audits and legal standards check against; AAA (7:1 / 4.5:1) is stricter. A blue badge on this page means a pair clears the large-text threshold but not the small-text one — a partial pass worth noticing before you use that color for body copy.

Examples

The WCAG formula, standalonejs
const channel = (c) => {
  const v = c / 255;
  return v <= 0.03928 ? v / 12.92 : ((v + 0.055) / 1.055) ** 2.4;
};
const luminance = ({ r, g, b }) =>
  0.2126 * channel(r) + 0.7152 * channel(g) + 0.0722 * channel(b);

const bg = { r: 0, g: 0, b: 255 };     // #0000ff
const fg = { r: 255, g: 255, b: 255 }; // #ffffff
const [l1, l2] = [luminance(bg), luminance(fg)].sort((a, b) => b - a);

console.log(((l1 + 0.05) / (l2 + 0.05)).toFixed(1)); // "8.6"

This is the same formula the tool runs on every keystroke — no color library involved. It’s also the pair the checker loads by default (Background #0000ff, Foreground #ffffff).

Default swatch — passes everythingtext
Background:  #0000ff
Foreground:  #ffffff
Ratio:       8.6:1

WCAG AA    ✓ small   ✓ large
WCAG AAA   ✓ small   ✓ large

The tool’s default pair. Both badges render green because 8.6:1 clears every threshold: AA small (4.5), AA large (3), AAA small (7), and AAA large (4.5).

A gray that only half-passes AAAtext
Background:  #767676
Foreground:  #ffffff
Ratio:       4.5:1

WCAG AA    ✓ small   ✓ large   (green — full pass)
WCAG AAA   ✗ small   ✓ large   (blue — partial pass)

4.5:1 clears AA outright but only clears the AAA large-text minimum (4.5), not the AAA small-text minimum (7) — that mismatch is what turns a badge blue instead of green or red.

Frequently asked questions

What contrast ratio do I need to pass WCAG AA?

WCAG 2.1 AA requires at least 4.5:1 for normal (small) text and 3:1 for large text — 18pt/24px regular or 14pt (about 19px) bold. AAA raises those minimums to 7:1 and 4.5:1.

What counts as large text under WCAG?

WCAG defines large text as at least 18pt (24px) at regular weight, or at least 14pt (about 19px) when bold. Anything smaller has to clear the stricter small-text ratio instead.

Does it matter which color goes in Background vs Foreground?

No. The ratio is calculated from the higher and lower relative luminance of the two colors, not from which field they’re typed into, so swapping Background and Foreground produces the identical ratio.

Why does the ratio show 1.0:1 while I’m still typing a color?

The checker only accepts a complete 3- or 6-digit hex code, like #00f or #0000ff. Until both fields hold a valid hex value the color fails to parse, and the ratio falls back to 1.0:1 — the same value two identical colors would produce.

What’s the highest contrast ratio possible?

21.0:1, between pure black (#000000) and pure white (#ffffff). The lowest is 1.0:1, which is what any color paired with itself produces.