Accessible color comes down to two separate questions that are often confused. Can someone see the difference between your text and its background? And does anything in your interface depend on distinguishing hues that some people cannot distinguish? A design can pass the first and fail the second badly. This guide covers both, and what to do about each.

What a contrast ratio actually measures

Contrast ratio compares the relative luminance of two colors — how much light each one sends to the eye. It is a number between 1:1 (identical) and 21:1 (pure black on pure white).

The calculation is worth understanding, because it explains results that otherwise look wrong. Each RGB channel is normalised to 0–1, gamma-corrected, then combined with fixed weights:

L = 0.2126 × R + 0.7152 × G + 0.0722 × B

Green carries 71% of the weight. Blue carries 7%. That is not arbitrary — human vision is far more sensitive to green wavelengths. The ratio is then (L1 + 0.05) / (L2 + 0.05) with the lighter color on top.

Two consequences follow. A saturated yellow is a very light color by this formula and almost always fails against white. A saturated blue is very dark and usually passes against white while failing against black. And crucially, HSL lightness is not luminance — hsl(60 100% 50%) and hsl(240 100% 50%) claim identical lightness and have wildly different luminance. Never estimate contrast from an L value. Run the pair through the contrast checker and read the actual number.

The thresholds, and what they apply to

ContentLevel AALevel AAA
Normal text4.5:17:1
Large text3:14.5:1
UI components & graphics3:1

Large text means roughly 24px and above at regular weight, or roughly 18.66px and above at bold. The threshold is lower because larger letterforms have more visible mass, not because the text matters less.

The third row is the one teams miss. Under WCAG 2.1, non-text elements that convey meaning need 3:1 against what is next to them: input borders, focus rings, toggle states, icon buttons, the meaningful parts of a chart. A pale grey border on a white field is a very common failure. So is a focus ring that only shows against half your backgrounds.

What is exempt: disabled controls, decorative graphics, logos, and text in a photograph. Disabled elements being exempt is not permission to make them illegible — it is an acknowledgement that they are deliberately de-emphasised.

Fixing a failing pair without losing the brand

The instinct when a combination fails is to abandon the color. Almost never necessary. Contrast is driven by lightness, so adjust lightness and leave hue alone:

  1. Convert the pair to HSL — the RGB to HSL converter does this in one step.
  2. Move the text color's lightness away from the background's. Darken dark-on-light; lighten light-on-dark.
  3. Re-check. Repeat in small steps until you clear the threshold with a little margin.

The hue is untouched, so it still reads as the brand color, just at a usable strength. The shade and tint generators produce these stepped variants directly.

Two specific situations come up constantly. Brand color as a button background with white text — many brand colors land between 3:1 and 4.5:1 against white, which passes for large text and fails for the label. Darken the button background rather than switching to a different hue. Grey body text on white — the classic light-grey-on-white look. #999999 gives about 2.8:1 and fails outright; you need roughly #767676 to reach 4.5:1. If your design calls for softer text, get it from size and weight, not from washed-out grey.

Color vision deficiency: the other half

Around 8% of men of northern European descent and roughly 0.5% of women have some color-vision deficiency. In a product with a hundred thousand users that is thousands of people, so it is not an edge case.

The common types:

  • Deuteranomaly and deuteranopia — reduced or absent green sensitivity. By far the most common. Red and green become hard to separate.
  • Protanomaly and protanopia — reduced or absent red sensitivity. Reds also appear darker than they do to typical vision, which affects perceived contrast as well as hue.
  • Tritanopia — blue-yellow confusion. Rare.
  • Achromatopsia — no color vision at all. Very rare, and the strictest test: if your interface works in greyscale, it works for everyone.

Contrast ratio does not catch these, because it only measures luminance. Two colors can sit comfortably above 4.5:1 and still be indistinguishable to a deuteranope. The color blindness simulator applies the standard transformation matrices so you can see which of your colors collapse together.

Never let hue carry meaning alone

This is the single most useful rule in accessible design, and it is a design rule rather than a math one. If the only difference between two states is hue, that difference does not exist for some of your users.

Everywhere this shows up, the fix is to add a second channel of information:

  • Form validation — a red border becomes a red border plus an icon plus a text message. The message was always the accessible part.
  • Status indicators — a green dot and a red dot become dot plus label, or two different shapes.
  • Charts — series distinguished only by color become series distinguished by pattern, direct labelling, or varying lightness rather than hue. Direct labels beat legends for everyone.
  • Links in body text — links distinguished only by color need underlines. This is why the underline convention exists.
  • Required fields — a red asterisk is a red asterisk plus the word "required".

Notice the pattern: every fix helps people without a color-vision deficiency too. Labelled charts are easier for everyone. Explicit error text is clearer than a red glow. Accessibility work of this kind is usually just clarity work.

Dark mode needs its own check

A palette validated on white does not transfer to a dark surface. Contrast is relative, so both sides changed.

Two things to know. Pure white text on pure black scores 21:1 and is genuinely uncomfortable to read at length — the halation effect makes letterforms smear for many readers, particularly those with astigmatism. Most well-built dark themes use an off-white on a dark grey, typically landing somewhere around 15:1, which is easier on the eye and still far above requirement.

Second, saturated colors behave differently on dark. A vivid blue that was perfectly readable on white can vibrate unpleasantly on near-black. Dark themes generally want desaturated, lighter variants of the same hues — which is what the tone generator produces. Build the dark palette as a deliberate variant, not as an inversion.

A practical checklist

  1. Every text-on-background pair clears 4.5:1, or 3:1 if genuinely large.
  2. Borders, focus rings and meaningful icons clear 3:1 against their surroundings.
  3. Focus indicators are visible on every background they can appear on.
  4. No state, status or data series is distinguished by hue alone.
  5. The palette survives the color blindness simulator without two meaningful colors merging.
  6. The dark theme has been checked separately, not assumed.
  7. The interface is still usable in greyscale.

Run this while the design is still in a mockup. Every item is a few seconds of checking then and a rebuild later.

Our practical WCAG contrast guide works through the fixing loop in more detail, and the color harmony guide covers building a palette that is accessible from the start rather than corrected afterwards.