Legibility is a feature, not a finishing touch.
Judge the pair in context, then use the inspector to tune its role, size, and weight. Contrast is measured from the rendered solid colors.
Check a colour pair against WCAG 2.2 on real type at the size and weight you actually ship, and get the nearest colour that passes instead of a bare fail. All three thresholds are reported at once, so you can see whether a pair that misses body text still works for a heading or an icon.
Step by step
01Set the pair
Foreground and background, in any CSS colour notation. The specimen renders live, so you are judging real type rather than two swatches side by side.
02Match the type you actually ship
Size and weight decide which threshold applies. 18px at weight 500 is body text; 24px, or 18.66px bold, is large text and drops to 3:1.
03Read all three verdicts
UI and large text at 3:1, AA body at 4.5:1, AAA body at 7:1 are reported together. A pair that fails body copy may be perfectly fine for a heading or an icon.
04Take the nearest passing colour
When a pair fails, the suggested fix moves lightness only — keeping the hue and chroma of your brand colour — and stops at the first value that clears the threshold.
Worked example
The common case: a brand colour that misses AA on white. The fix searches lightness at 201 steps in OKLCH, holding hue and chroma fixed, and takes the smallest move that passes.
Given
What the repair actually changes
before #7C93B8 on #FFFFFF 3.12:1 fails AA
passes nothing
search hue and chroma held
lightness stepped 0 -> 1 in 201 steps
first value clearing 4.5:1 wins
after #61779A on #FFFFFF 4.55:1 passes AA
same hue family, darkerContrast is almost entirely a lightness relationship, which is why moving only lightness usually fixes a pair while leaving it recognisably the same colour. It also explains the failure people find most surprising: two colours that look completely different — a mid blue and a mid red — can sit at nearly identical lightness and have almost no contrast at all.
Before you sign it off
The threshold depends on the type, not the colour
4.5:1 for body text, 3:1 once text is 24px, or 18.66px and bold, and 3:1 for interface components and their focus states. Checking a pair without knowing which size it will be used at answers a question you have not asked yet.
Hue difference is not contrast
The ratio is computed from relative luminance, so a saturated red on a mid green can look violently different and still fail badly. If you squint until the colours blur and the text disappears, no amount of hue separation will save it.
Ratios are the floor, not the goal
4.5:1 is the point at which the guideline stops objecting, not the point at which reading becomes comfortable. Long-form copy, small type, and low-quality screens all benefit from more, and going past AA costs you nothing but a slightly darker colour.
Disabled states and placeholders still get read
They are routinely exempted on the grounds of being inactive, and users still need to read them to know what a form wants. A greyed-out label at 2:1 is a real barrier, whatever the guideline permits.
Test the colour that will actually be behind it
Text over a photograph, a gradient, or a translucent overlay has a different ratio in every part of the frame. Check the worst region rather than the average, or put a solid scrim behind the text so there is one number to check.
WCAG 2 has known blind spots
The formula is a good tool and a rough model of perception: it is harsher on light-on-dark pairs than experience suggests and lenient on some mid-tone combinations. Treat a marginal pass on a dark theme as a prompt to look at it, not as proof.
The judgement call
Most contrast arguments are really disagreements about which rule the element falls under.
Body copy, paragraphs, form labels
4.5:1
AA for normal text. The practical baseline for anything a reader has to work through.
Headings 24px and up, or 18.66px bold
3:1
Large text threshold. Bigger glyphs carry more of the shape, so less contrast is needed to read them.
Icons, borders, focus rings, chart lines
3:1
Non-text contrast covers anything you must perceive to use the interface.
Long-form reading or a low-vision audience
7:1
AAA. Not required in most policies, and noticeably easier on the eye for sustained reading.
Text over a photo or a gradient
Check the worst spot
The ratio varies across the image. Test the lightest region, or add a scrim so there is a single value to verify.
Purely decorative text or a logotype
Exempt
WCAG excludes logotypes and incidental text — but if a user has to read it, it is not decoration.
Reference
FAQ
4.5:1 for normal body text under WCAG AA, dropping to 3:1 once text reaches 24px or 18.66px bold. Interface components, icons, and focus indicators need 3:1. AAA raises body text to 7:1, which is worth aiming at for long-form reading even where it is not required.
Contrast is calculated from relative luminance, not from how different two colours look. A saturated red and a mid green can be unmistakably different in hue and sit at almost the same lightness, which leaves the text barely readable. Squint at the pair: if the text disappears, so does the ratio.
Move lightness and leave hue and chroma alone — which is exactly what the suggested colour here does. It steps lightness in OKLCH and takes the first value that clears your target, so the result stays recognisably the same colour, just lighter or darker.
WCAG exempts disabled controls, and placeholders are frequently argued about. Users still have to read both to understand a form, so treating the exemption as permission to go to 2:1 creates a genuine barrier. Aim for at least 3:1 on anything carrying meaning.
Up to a point. Pure black on pure white reaches 21:1 and some readers find that glare uncomfortable for long passages, which is why many designs use a very dark grey instead. Comfortably above the threshold is the target, not the maximum.
Yes. Ratios, verdicts, and the suggested repair are all computed in your browser, and the share link carries only the two colours and your type settings.
Ratios, verdicts, and the suggested repair all run in your browser. Share links carry only the colours and type settings.
Keep going
Color Converter
See the same colour in OKLCH and nudge its lightness directly.
Palette Generator
Build a token scale whose steps already clear the thresholds.
Vision Simulator
Check the pair still separates for a colour-blind reader.
Named Color Library
Look up a CSS named colour and its contrast behaviour.