What the ratio actually measures
Contrast, as the accessibility guidelines define it, is a comparison of light rather than of colour. Each of the two colours is converted to a relative luminance — the three channels weighted for how bright the eye perceives them, with green counting for far more than blue — and the two luminances are compared as a ratio between 1 and 21.
Identical colours give 1:1. Black against white gives 21:1. Everything else falls in between, and the [msm_tool slug="color-contrast"] reports where a given pair lands.
Because it measures light and not hue, two colours that look obviously different to you can still fail. A mid-blue and a mid-green of similar lightness are visibly distinct and contrast poorly, and that is the point rather than a flaw in the formula: it is modelling readers who do not distinguish those hues, or who are looking at a dim screen in bright sun.
The thresholds, and which one applies
- 4.5:1 — the AA minimum for normal body text. This is the figure that matters most often, because body copy is where readability is won or lost.
- 3:1 — the AA minimum for large text, meaning roughly 24px, or 19px when bold.
- 3:1 — also the minimum for non-text elements that carry meaning: borders, focus rings, icons, form field outlines, chart segments.
- 7:1 — the enhanced AAA level for normal text, and 4.5:1 for large text at AAA.
A heading that fails the normal-text check may well pass at its actual size, so it is worth knowing which threshold you are testing against before concluding that a palette is unusable.
The interface elements everyone forgets
Text gets checked. Borders, focus rings and icons usually do not, and they are held to 3:1 against whatever surrounds them.
The focus ring is the one worth singling out. A keyboard user needs to see where they are on the page, and a focus indicator at 1.5:1 against the background is technically present and practically invisible. The default browser ring meets the bar; a custom one frequently does not, and removing it entirely without replacement is the most common accessibility fault on the web.
The same applies to form fields. An input whose only boundary is a pale grey line at 1.8:1 is a field that some people cannot find.
Placeholder text is not a label
Two separate problems, both common.
Placeholder text is usually styled grey specifically so it reads as a hint, which routinely puts it below 4.5:1. If the placeholder carries information the user needs, that information is failing contrast. If it does not carry information, it is decoration in a field.
Worse, placeholder text disappears the moment someone starts typing. Using it instead of a label means the field's name vanishes exactly when it is needed — while checking what you have entered. Use a real label and let the placeholder show an example format, or nothing.
Text over images and gradients
There is no single background colour to test, which is why this case is usually skipped and frequently broken.
Sample the lightest and darkest points the text actually crosses and make sure the worst of them passes. If it does not, the fixes in rough order of reliability are: a solid or semi-opaque panel behind the text, a gradient scrim over the image beneath the text, or moving the text somewhere calmer in the frame. A text shadow is not a fix — contrast is measured between the text colour and the background, and a shadow does not enter the calculation at all.
Where the ratio does not tell you enough
- Very thin type. A hairline weight at 4.5:1 is harder to read than a regular weight at the same ratio. The formula does not know about stroke width.
- Large areas of saturated colour. A page of white text on bright red passes comfortably and is tiring to read for reasons the ratio does not capture.
- Dark mode. Pure white on pure black passes at 21:1 and produces visible halation for many readers. An off-white on a dark grey is usually more comfortable and still passes easily.
- Disabled controls. Deliberately low contrast to signal unavailability, and exempt from the requirement — but if people cannot tell a disabled button from an enabled one, that is a different problem.
Fixing a failure without redesigning
The instinct is to change the brand colour, and it is usually unnecessary. Most failures are fixed by adjusting the lightness of one of the two colours while leaving its hue and saturation alone — the colour stays recognisably itself and the ratio moves considerably.
Where a brand colour genuinely cannot carry text, use it for something that is not text: a border, a background behind white text at a larger size, an accent on a component rather than the component's label. A colour failing at body size is not a colour you have to abandon.