skip to main content

-- Measure the contrast ratio of two colours, check the AA and AAA levels, and get the closest compliant variant --

an alpha channel is accepted then ignored: compositing a transparent colour would require knowing what sits behind it.

contrast ratio4.48:1

normal text, 16 px

large text, 24 px

  • normal text AA (4.5:1)fail
  • normal text AAA (7:1)fail
  • large text AA (3:1)pass
  • large text AAA (4.5:1)fail
  • UI components (3:1)pass

the closest variant reaching 4.5:1 is #767676.

How to use it

Enter two colours in hexadecimal or rgb(). The tool computes the ratio, tests the five WCAG thresholds, and — when the contrast falls short — suggests the closest variant of your colour that reaches level AA.

The thresholds

CriterionTargetMinimum ratio
1.4.3normal text, level AA4.5:1
1.4.3large text, level AA3:1
1.4.6normal text, level AAA7:1
1.4.6large text, level AAA4.5:1
1.4.11input borders, meaningful icons3:1

"Large text" means at least 24 px, or 18.66 px bold. Below that, the 4.5:1 threshold applies.

Criterion 1.4.11 is the one most often forgotten: a form field's border, a focus state, an icon carrying information all have to reach 3:1 against their background. A border-gray-200 on white sits at 1.24:1 — far below.

The formula

const linearize = (channel) => {
  const ratio = channel / 255;
  return ratio <= 0.03928
    ? ratio / 12.92
    : ((ratio + 0.055) / 1.055) ** 2.4;
};
 
const luminance = ({ r, g, b }) =>
  0.2126 * linearize(r) +
  0.7152 * linearize(g) +
  0.0722 * linearize(b);
 
const contrast = (a, b) => {
  const [hi, lo] = [luminance(a), luminance(b)].toSorted(
    (x, y) => y - x
  );
  return (hi + 0.05) / (lo + 0.05);
};

Two details matter. First the per-channel linearisation: it is not a division, it is a gamma curve. Then the coefficients: green weighs 0.7152 against 0.0722 for blue, because the eye is far more sensitive to it.

The approximation you sometimes see — averaging the three channels — lets pairs through that genuinely fail.

Transparency cannot be measured alone

An alpha channel is accepted by the tool then ignored, and that is deliberate: compositing #1e40af80 requires knowing what sits behind it. On white and on black, the same semi-transparent colour yields two completely different ratios.

If your colour is semi-transparent, composite it against its real background first, then measure the resulting colour.

A few useful values

Colour on whiteRatioNormal text AA
#00000021:1yes
#5959597:1yes, and AAA
#7676764.54:1just barely
#7777774.48:1no

#767676 is the exact limit for grey used as normal text on white. One shade lighter and the criterion fails.

What contrast does not cover

A compliant ratio does not make an interface accessible. Colour must not be the only way information is conveyed (criterion 1.4.1): a field in error marked only by a red border stays invisible to a colour-blind person. It needs text, an icon, or both.

topics covered

related reading