Color Contrast Checker
The ratio, the verdict, and the two colours actually shown together.
Runs entirely in your browser
Loading the tool…
Large text, 24px bold
Body text at 16px, which is the size most of a page is set in and the one the 4.5:1 threshold was written for.
—
| Body text AA, 4.5:1 | — |
|---|---|
| Body text AAA, 7:1 | — |
| Large text and UI AA, 3:1 | — |
Two colours in, one number out. 4.5:1 is the threshold for body text under WCAG AA, 3:1 for large text and user interface parts, and 7:1 for AAA. The pair is rendered above the table as well as scored, because a ratio is a number and readability is something eyes settle faster.
The ratio is computed from relative luminance, not from how different the two colours look. That is why it so often disagrees with the eye: a mid grey and a mid blue can look strongly different and still fail, because contrast here is about light and dark rather than about hue. Two colours of the same lightness have a ratio near 1:1 however far apart they are on the wheel.
Contrast is symmetric but design is not, which is what the swap button is for. The same pair scores identically either way round, and dark text on a light panel and light text on a dark button are different design decisions that happen to share a number.
This site holds itself to the same rule. check-pages.py measures every
text colour against every surface it sits on, in both themes, and fails the build
under 4.5:1. It has caught unreadable tertiary text in two separate restyles, which
is the argument for checking rather than eyeballing: nothing else warned.
How to use it
- Put your text colour and your background colour in, or use the pickers.
- Read the ratio, and the sample above it in the two colours together.
- Press swap to check the same pair the other way round.
Questions
What color contrast ratio do I need?
4.5:1 for body text and 3:1 for large text under WCAG AA, where large means about 24px, or 19px if bold. AAA asks for 7:1 and 4.5:1. Interface parts that carry meaning, such as a form border or an icon a control depends on, need 3:1 as well, which is the requirement most often missed.
Why does a color that looks different still fail?
Because the ratio is computed from relative luminance, which is about light and dark rather than about hue. Two colours of similar lightness have a ratio close to 1:1 however far apart they look, which is why mid-tone pairs and colour-on-colour combinations fail so often while looking perfectly distinct.
Does the ratio change if I swap the colours?
No, it is symmetric: the formula divides the lighter luminance by the darker one whichever order you give them in. What changes is the design. Swapping is worth doing anyway, because the same pair often reads well one way round and badly the other once real type is set in it.
Is a 4.5:1 pass enough for accessibility?
It is a floor rather than a finish. It says nothing about type size, weight, line length, whether meaning is carried by colour alone, or how the page behaves at 200% zoom. A page can pass every ratio on it and still be hard to read, which is why the number is the beginning of the check and not the end.
Is anything sent anywhere?
No. The arithmetic runs in WebAssembly inside this tab, and the page is served with a header forbidding it from opening a connection to anywhere at all. It works with the network off.
Your data stays on your device
Everything above runs inside your browser as WebAssembly compiled from Rust. Nothing you type is uploaded, logged or stored on a server. You can load this page once, go offline, and it still works.
This page makes no requests at all, to anywhere. That is not a promise in the copy: it is a Content-Security-Policy header your browser enforces, and connect-src on it is none. Open the network tab and watch nothing happen.