WCAG defines text legibility through a single number called the contrast ratio, calculated as (L1 + 0.05) / (L2 + 0.05), where L1 is the lighter color's relative luminance and L2 is the darker one. To pass Level AA you need at least 4.5:1 for normal text and 3:1 for large text; to pass Level AAA you need at least 7:1 for normal text and 4.5:1 for large text. Non-text contrast — UI controls, icons, form borders, focus rings — needs at least 3:1 under WCAG 2.x. A color contrast checker encodes those thresholds into clear pass or fail badges so you can see at a glance whether your foreground and background meet the level you are aiming for, and it does the math the WCAG specifies: each sRGB channel is linearized, then combined into a relative luminance using the weights 0.2126 for red, 0.7152 for green, and 0.0722 for blue, before the ratio is computed. That gives you a single trustworthy number to design against.

How the WCAG Contrast Formula Works
The math under the hood is short, and once you see it the badges stop feeling mysterious. Each color is converted from its sRGB channel value into a linear-light value: very dark channels (below 10 on the 0 to 255 scale) are simply divided by 12.92, and brighter channels are transformed with ((c / 255 + 0.055) / 1.055) raised to the 2.4 power. The three linear channels are then combined into a relative luminance using the official weights — 0.2126 for red, 0.7152 for green, and 0.0722 for blue — which model how the human eye weighs brightness. The ratio is then the lighter luminance plus 0.05, divided by the darker luminance plus 0.05, which guarantees the value lands between 1:1 (identical colors) and 21:1 (pure black on pure white).
Let me walk through one pair to show how the formula plays out. Take #767676 as the foreground and #ffffff as the background — a combination designers reach for when a soft gray is needed on a white page.
Step 1 — linearize the gray. The red, green, and blue channels are all 118, so 118 / 255 ≈ 0.463, then ((0.463 + 0.055) / 1.055)^2.4 ≈ 0.181. The white background linearizes to 1.0 in every channel.
Step 2 — relative luminance. 0.181 × (0.2126 + 0.7152 + 0.0722) ≈ 0.181, because the three weights sum to 1.
Step 3 — contrast ratio. (1 + 0.05) / (0.181 + 0.05) = 1.05 / 0.231 ≈ 4.54:1.
That is just barely above the 4.5:1 AA threshold for normal text, which is exactly why #767676 is famous as the lightest gray you can put on white without failing. The deeper explanation lives in the W3C contrast-minimum note, and the thresholds themselves map onto a clean reference table:
| Content type | AA minimum | AAA minimum |
|---|---|---|
| Normal text | 4.5:1 | 7:1 |
| Large text (18pt regular or 14pt bold) | 3:1 | 4.5:1 |
| UI components and graphical objects | 3:1 | 3:1 (no separate AAA) |
Check a Color Pair in Three Steps
This is the practical workflow inside the Color Contrast Checker:
- Set the foreground (text) color. Open the color picker, type a hex like #111111, or paste a swatch straight from your design system. The picker accepts any valid six-digit hex.
- Set the background color the same way — pick it or type it, for example #ffffff for a white canvas.
- Read the contrast ratio and the AA/AAA badges for normal text, large text, and UI components. Adjust either color until every badge you care about shows a pass.
That is the whole loop: pick, pick, read, nudge. If you are aiming at AA only, set your sights on 4.5:1 for normal text and 3:1 for large text. If you are designing for AAA, or for long reading sessions on cheap screens in bright sun, push toward 7:1 or higher. The badges update in real time, so the moment you shift a hue by a couple of points you can see exactly which thresholds you cleared or broke.
Where Contrast Checks Go Wrong
Most failed audits are not the result of bad math. They come from a small set of predictable mistakes that even experienced teams repeat.
Treating AA as a ceiling. AA is the legal floor in most jurisdictions that reference WCAG, not the comfort zone. Body copy at exactly 4.5:1 reads fine on a calibrated monitor in a dark office, then washes out on a low-end laptop, in sunlight, or for readers with low vision. If your audience is broad, design for AAA where you can, especially for long-form paragraphs and small UI labels.
Forgetting the large-text rules. Large text gets a relaxed threshold — 3:1 for AA, 4.5:1 for AAA — but only when the type really qualifies: 18pt regular, or 14pt bold. A 16px caption set at 700 weight still counts as normal text in the eyes of the formula, so check the actual rendered size and weight, not the design intent.
Ignoring non-text contrast. UI controls, focus indicators, icon buttons, and form-field borders live under a separate rule: at least 3:1 against adjacent colors. A link that passes 4.5:1 as text can still have an underline or chevron that disappears against the background. Run those elements through the same checker before you ship them.
Relying on color alone. Contrast is about luminance, not hue. A red label on a green field can look obvious to some viewers and indistinguishable to readers with red-green color vision deficiency. Pair color with an icon, a label, or an underline so the meaning does not depend on the hue alone.
Checking only one screen state. Hover, focus, disabled, and error states are common failure spots. Many teams verify the default state and then ship an inaccessible disabled button that fades to 50% opacity over the same background — the ratio plummets, and the button effectively vanishes against the page. The good news is that the contrast pass takes only a moment, so there is no reason to skip it on secondary states.
What the Ratio Does Not Cover
The contrast number is precise, but it answers one question only: how different in luminance are these two colors. Everything else is on you.
Semi-transparent layers and overlays. A 70%-opaque black on a colored background does not have a stable contrast ratio; the effective background changes with whatever the overlay is sitting on. Test the resulting composite, not the raw overlay color, and check it against both the lightest and darkest surfaces it could appear on.
Gradients. As a label crosses a gradient, the color behind it shifts. Test the lightest and darkest stops. If the ratio dips below threshold mid-gradient, the gradient is unsafe for text.
Text on images. Photographs and illustrations have no fixed background. Either darken the area behind the text with a scrim or test several points where a letter could land and use the worst case as your pass criterion.
Hue-only signals. Two very different hues at the same luminance — say a #555 red on a #555 green — can look distinct to fully sighted viewers and still fail WCAG. The ratio is the tie-breaker, not the color wheel.
Placeholder text. Browsers render placeholders at reduced opacity, often around 40%. The effective contrast against the input background can dip below 2:1 even with dark mode enabled. Override the placeholder color explicitly with a tested high-contrast value, then run the resulting color through the checker to confirm.
Tips for Building a Palette That Always Passes
A few habits make a contrast checker feel less like a final exam and more like a routine checkpoint.
Test the brand palette first. Run your primary, secondary, and accent colors against white, off-white, and dark backgrounds before any layout work starts. Catch the fails at the token stage and you avoid retrofitting dozens of components later. A quick web accessibility check alongside the design tokens keeps brand, accessibility, and runtime in agreement.
Lock the lightest gray. If your design system needs a "subtle gray text," set it to the lightest value that still passes 4.5:1 on white and on every dark surface you ship. #767676 on white is the boundary; anything lighter fails, anything darker is safe. Codify that boundary as a token so no one drifts below it.
Treat large-text exemptions carefully. Reserve the relaxed threshold for true headings and hero copy. As soon as a 14pt bold element functions as a control label or a navigation item, treat it as normal text so the WCAG pass or fail is unambiguous.
Keep a running list of contrast pairs. A short reference table that pairs each brand color with its safe foreground (and vice versa) lets the rest of the team pick a pair without re-running the checker each time.
Verify after every color change. As soon as anyone nudges a brand hue by a few points, re-run the affected pairs. A shift from #1a73e8 to #1a72e8 looks identical to the eye but can pull a link color under threshold on a particular background.
A contrast checker is one of the few tools where the math is unambiguous and the rules are written down. Use it the way it was designed to be used: pick two colors, read the badges, iterate until they pass, and remember that the ratio is a measure of luminance, not of meaning. Everything runs locally in your browser, so you can experiment with brand palettes and design tokens privately without uploading anything.
For a deeper look, see Color Difference Calculator Tips and Avoid Common Mistakes.