Contrast Checker
Check color contrast ratios for WCAG AA and AAA compliance.
About This Tool
What this tool does
The Contrast Checker measures how readable one color is on top of another and tells you whether that pairing clears the WCAG accessibility thresholds for text. You pick a text color and a background color, and it returns a single contrast ratio (something like 14.63:1 or 4.5:1) along with four Pass or Fail badges, one for each of the four bars in the WCAG 2.x text-contrast rules. The page opens with a dark slate text color (#1e293b) on a white background as its starting example, which produces a 14.63:1 ratio and passes every level.
Who needs to use it
Anyone who is shipping text on a screen and wants to confirm it stays legible. The common audiences:
- Designers sanity-checking a palette before handing it to engineering — especially when a brand color sits close to a neutral and you suspect it might fail AA.
- Frontend developers auditing tokens (
--text-secondary,--text-muted, placeholder color, disabled-state color) that tend to drift toward "too pale" over time. - Accessibility reviewers producing a written record that a pairing meets AA, which is the level most accessibility laws and procurement audits reference.
- Anyone making a slide deck, dashboard, or marketing page who has had a stakeholder squint at the screen and ask "can you read that?" once too often.
How to use it
There are only two controls. Click the Text Color swatch to open your operating system's native color picker and choose the foreground (the color of the actual letters). Click the Background Color swatch and pick the color that sits directly behind those letters. The Result card recalculates instantly on every change — no submit button, no debounce.
The result card shows five lines. The top line is the contrast ratio itself, written in the standard X:1 form and rounded to two decimal places. Below it are four pass/fail badges:
- AA Normal Text — needs 4.5:1. This is the bar most people are aiming for. It applies to ordinary body copy, captions, and labels.
- AA Large Text — needs 3:1. Applies to text that is at least 18pt (about 24px) at regular weight, or at least 14pt (about 18.66px) at bold weight and above.
- AAA Normal Text — needs 7:1. A stricter target. Useful for long-form reading content where you want extra legibility headroom; not legally required by most standards.
- AAA Large Text — needs 4.5:1. The AAA equivalent for the larger-text size bucket.
Pick whichever badge corresponds to the size and weight of the text you're actually shipping. For everyday body copy, the one that matters is AA Normal Text (4.5:1).
How it works under the hood
The tool runs the standard WCAG 2.x contrast-ratio calculation in three steps, all in your browser as you change the inputs.
Step 1: hex to relative luminance. Each color is split into its red, green, and blue channels (each 0–255) and divided by 255 to land in the 0–1 range. Each channel is then linearized to undo the sRGB gamma curve: if the channel is at or below 0.03928, it is divided by 12.92; otherwise it is raised through ((channel + 0.055) / 1.055) ^ 2.4. Linearized channels are then combined as a weighted sum:
L = 0.2126 × R + 0.7152 × G + 0.0722 × B
Those weights reflect how human vision responds to each primary — green contributes the most, blue the least — which is why bright yellow looks luminous and pure blue looks dark even at full saturation.
Step 2: the ratio. Compute (L1 + 0.05) / (L2 + 0.05), where L1 is the luminance of the lighter color and L2 the darker. The + 0.05 term models a small amount of ambient screen reflection, and it neatly prevents division by zero when one color is pure black. The result is always at least 1:1 and at most 21:1.
Step 3: round and compare. The ratio is rounded to two decimal places and checked against the four thresholds (4.5, 3, 7, 4.5). Each comparison produces the corresponding Pass or Fail badge.
One footnote for the very precise: WCAG 2.1 quietly swapped the linearization cutoff constant from 0.03928 to 0.04045. The difference is negligible in real-world checks — almost no color pair lands in the sliver between those two values — and most contrast tools, this one included, still use the original 0.03928. If your audit requires the newer constant exactly, flag it and verify against a tool that exposes its source.
Worked example
Let's walk through the default. Text is #1e293b (a deep slate), background is #ffffff (white).
For the text color, the channels are 0x1e = 30, 0x29 = 41, 0x3b = 59. Divided by 255 those become roughly 0.118, 0.161, 0.231. All three are above 0.03928, so each is linearized with the power formula and the weighted sum lands at L ≈ 0.0226. White's luminance is 1.0 exactly. The ratio is (1.0 + 0.05) / (0.0226 + 0.05) ≈ 14.63, which the tool displays as 14.63:1. Every badge says Pass.
Now try #777777 on white — the classic "looks like a fine medium gray" that most people assume is safe. Its luminance is about 0.184, and the ratio comes out to 4.48:1. That's a Fail on AA Normal (it needs 4.5), a Pass on AA Large, a Fail on AAA Normal, and a Fail on AAA Large. The number is striking: 0.02 away from passing. Bumping the gray one shade darker, to #767676, just barely clears the 4.5 bar — which is why so many design systems pick that exact gray for muted text. Going the other direction, #959595 on white lands almost exactly at 3:1 — that's the floor for AA Large text.
Common pitfalls
- "Large text" isn't what most people think. A 16px body paragraph is normal text, even if it is your heading-sized headline in a tiny modal. The 3:1 bar only applies once you cross 18pt regular (24px) or 14pt bold (about 18.66px). When in doubt, hold yourself to 4.5:1.
- Transparent colors don't tell the truth. The pickers only produce solid hex colors, but lots of real text sits on a semi-transparent overlay (a
rgba(0,0,0,0.6)scrim on top of a hero image, a--text-mutedtoken defined ascolor-mix(...), or a glass-effect card). Contrast depends on the pixels a viewer actually sees, so flatten the semi-transparent color against whatever sits behind it first, then paste the resulting solid hex into the tool. - Photos and gradients behind text break the assumption. A contrast ratio is meaningful only for a single foreground against a single background. If your text crosses a gradient or sits on a photo, the worst-case pixel under the text is what matters — usually a brightish midtone — and you should check against that, not against an "average" color you eyeballed.
- Placeholder text and disabled states are where most real audits find failures. Designers often style them as a light gray that looks appropriately faded but lands somewhere around 3:1 on white. AA requires 4.5:1 for placeholder text that conveys information. If you only check one set of tokens today, check those.
- Hover, focus, and visited states each have their own foreground/background pair. Don't assume the resting state passing implies the hover state passes.
- Brand colors are not exempt. A logo can use any color, but the moment you set body text in a brand orange on white, that pairing has to clear 4.5:1 like everything else. If the brand color won't pass, use it for icons or large display text where 3:1 applies, or pair it with a darker neutral for body copy.
What to do if the result looks wrong
The most common "this can't be right" moments:
- "Two colors look identical to me but the ratio is 1.5:1, not 1:1." Trust the math. Human perception is unreliable for small lightness differences, especially in midtones. Open the colors in any other contrast checker — they will agree.
- "My gray passes AA on one site and fails on another." Check the background. Designers tend to test on pure white, but a card sitting on
#f8f9fa(a typical off-white "background-subtle") changes the contrast against the gray inside the card. Pure-white assumptions are a frequent source of "passes in Figma, fails in production" bugs. - "My hex code is shorter than six characters." The native color picker always returns a 6-digit hex, so if you typed a 3-character hex (
#abc) into a tool elsewhere and got a different answer, that tool was expanding it to#aabbccfirst. This tool does the equivalent under the hood because the input is locked to 6-digit.
When NOT to use it
- Non-text UI elements with their own rule. The four badges shown here are for text. WCAG 1.4.11 ("non-text contrast") covers icons, form-control borders, focus indicators, and meaningful graphical objects — those need 3:1 against adjacent colors. You can still use the ratio in this tool for those checks; just read it against the 3:1 bar (the AA Large Text badge) instead of 4.5:1.
- APCA / WCAG 3. A newer contrast model called APCA (Advanced Perceptual Contrast Algorithm) is being developed for WCAG 3 and produces different numbers (it scores on a roughly -108 to +106 lightness-contrast scale, not a ratio). APCA is more perceptually accurate, especially for dark mode and thin fonts, but it is not yet the legal or standards-compliance bar in most places. If you're chasing AA or AAA, use this tool. If your team has explicitly adopted APCA, use an APCA-specific tool.
- Color-blindness checks. Passing 4.5:1 says nothing about whether your design works for someone with deuteranopia, protanopia, or tritanopia. Two colors with strong contrast can still be indistinguishable to a color-blind viewer (red text on a green button being the canonical example). For that, use a color-blindness simulator alongside the contrast check.
- Print. WCAG contrast is defined for emissive screens with a small ambient-light assumption baked into the
+0.05term. Print contrast is a separate discipline.
Adjacent concepts worth knowing
The 1.4.11 non-text rule — 3:1 for UI components and graphical objects — is the other contrast rule that lands on real audits. Form-input borders, the line under an underlined link, the icon inside an icon-only button, and your focus ring all need 3:1 against whatever they sit on. Focus rings in particular are frequent failures: a 1px light-blue ring against a white background often fails, even when the button itself passes.
Large text bonus. The 3:1 bar exists because larger text strokes are easier to resolve at lower contrast — your eye doesn't need to work as hard on a 32px headline as on a 13px footnote. Use the bonus honestly: don't shrink a "large" headline once it has passed and assume it still passes.
Dark mode flips the math but not the bar. The ratio is symmetric — white on black gives the same 21:1 as black on white — but the colors that need attention are different. Mid-dark grays on a near-black background are the dark-mode equivalent of light grays on white, and they fail in the same way.
A pass is necessary, not sufficient. A green badge here confirms that your text-versus-background contrast meets a specific WCAG number. It does not confirm that your font is large enough, that your line height is comfortable, that your hit targets are reachable, that the page works at 200% zoom, or that a screen reader can parse it. Treat the result as one box checked on a longer list.
Privacy
Every calculation runs locally in your browser. The colors you pick are never sent to a server, and the page works offline once it has loaded.
The about text and FAQ on this page were drafted with AI assistance and reviewed by a member of the Coherence Daddy team before publishing. See our Content Policy for editorial standards.