Color palette contrast checker (up to 12 colours)
Palette contrast checker
Up to 12 colours as hex, rgb(), hsl() or a colour name, with an optional name before a colon: "Primary: #2f47d9". CSS variables such as "--brand: #2f47d9;" work too.
Colours read
Text colour on background colour, by the WCAG 2.x formula. A semi-transparent colour is blended with the background first; a semi-transparent background is blended with white. The check runs in your browser; the colours are not sent anywhere.
The matrix needs JavaScript. Without it you can still read the contrast rules in the text below the tool.
Large text means at least 24 px, or 18.66 px in bold. Icons, field borders and other interface parts need 3 : 1 (WCAG 1.4.11). Logos and disabled controls are exempt.
Passing pairs
As CSS variables
As a Markdown table
A contrast checker answers one question for one pair. A brand has a dozen colours and dozens of pairs. Enter your palette, up to 12 colours, and the table shows the WCAG contrast ratio of every pair, which pairs are safe for text, and which only work for large text, icons and borders. The calculation runs in your browser; the colours are not sent anywhere.
How to enter the colours
One colour per line, or separated by semicolons. A name before a colon is optional: Primary: #2f47d9. Accepted are hex (also with alpha), rgb(), rgba(), hsl(), hsla(), colour names such as navy, and CSS custom properties copied from your stylesheet, like --brand-500: #2f47d9;. A line the checker cannot read is listed under the field, so a typo does not silently drop a colour. Semi-transparent colours are blended with the background first.
How to read the matrix
Rows are text colours, columns are backgrounds. Each cell shows a small picture of the pair, the ratio and the highest level it reaches:
| Badge | Ratio | What the pair is good for |
|---|---|---|
| AAA | 7 : 1 and up | Text of any size at the enhanced level (1.4.6) |
| AA | 4.5 : 1 and up | Text of any size (1.4.3), icons and borders |
| AA large text and UI | 3 : 1 and up | Large text (24 px, or 18.66 px bold), icons, field borders, focus indicators (1.4.3, 1.4.11) |
| Fails | below 3 : 1 | Decoration only; logos and disabled controls are exempt |
The ratio uses the WCAG 2.x formula and is cut, not rounded, to two decimals: 4.49 is not 4.5. Every cell also carries a text for screen readers ("Ink on Paper: 16.1 : 1, AAA"), and the table has row and column headers, so it can be read cell by cell with the keyboard.
Filter and export
Choose the level a pair must reach to count as passing, and tick "Show only passing pairs" to hide the rest of the matrix. The list below the matrix shows the passing pairs, best first. Copy as CSS variables gives you your palette as custom properties with the passing pairs as a comment; Copy as a Markdown table gives the passing pairs for a design-system page or a pull request.
What the matrix cannot tell you
- Interactive states. Hover, focus, active, visited and disabled colours are separate pairs; add them as their own lines.
- Backgrounds that are not flat. Text on a photo or a gradient needs a check at the lightest and the darkest spot, with the contrast checker, which can also pick colours from an image.
- Meaning carried by colour alone. A red error and a green success of the same lightness look alike to many people. WCAG asks for another cue as well, such as an icon or text (1.4.1 Use of Color).
- Contrast in your real pages. A palette that passes can still be used wrongly. Test the live page with the WCAG checker.
This is an automatic calculation, not a full audit, and not legal advice.
Building a palette that passes
Start from two anchors: a dark ink for text and a light paper for backgrounds. Check your brand colour against both, because most brand colours pass on one side only. Give each brand colour a darker shade for text on white and a lighter shade for text on dark. Keep a 3 : 1 tint for borders and icons, since non-text contrast applies to input borders and focus rings. The design decision to make is not which pair is allowed in theory, but which pairs the theme can reach in practice.
Under the EAA and the German BFSG, the standard EN 301 549 takes over WCAG contrast at level AA, so 4.5 : 1 and 3 : 1 are the numbers to design for. AAA is not required. Pandus checks the colours that your pages really use, on every page, every week.
Frequently asked questions
How many colours can I enter?
Up to 12. With 12 colours the matrix has 132 pairs. If you enter more, the first 12 are used and the checker says how many were left out.
Which formula does the matrix use?
The WCAG 2.x contrast ratio, (L1 + 0.05) / (L2 + 0.05) on the relative luminance of the two colours, cut to two decimals. It is the formula that WCAG 1.4.3, 1.4.6 and 1.4.11 refer to.
Are my colours sent to a server?
No. The matrix is calculated in your browser, and nothing about the palette is stored or sent.
Why is a pair different in the two directions?
It is not, for opaque colours: the ratio of A on B equals B on A. The matrix still shows both rows so that you can find a text colour quickly. With semi-transparent colours the two directions differ, because the text colour is blended with the background.
Does a passing palette make my site accessible?
No. It only means these pairs have enough contrast. Whether the pages use them correctly, and everything else in WCAG, still has to be checked.