Benchvale

Color contrast grid

A contrast grid checks every color in a palette against every other color at once and gives each pair its WCAG ratio and verdict. Every pair, with the number, free and without an account. Normal text needs 4.5:1, large text and interface graphics need 3:1. Checking pairs one at a time is how accessible-looking palettes ship with unreadable combinations.

Your palette

Rows are the text color. Columns are the background.

Text size

22 pairs passing AA

Normal text AA
22 of 56 (39%)
Normal text AAA
12 of 56 (21%)
Large text / UI AA
30 of 56 (54%)
Large text AAA
22 of 56 (39%)

No color in this palette is graphics-only: each one can hold normal text against at least one partner.

Every pair in your palette, with its WCAG ratio and verdict. Rows are the text color, columns are the background.
text \ background ink primary accent accent deep muted mist paper surface
inksame2.13:1 Failink on primary7.91:1 AAAink on accent2.83:1 Failink on accent deep3.19:1 Failink on muted11.53:1 AAAink on mist16.32:1 AAAink on paper17.52:1 AAAink on surface
primary2.13:1 Failprimary on inksame3.71:1 Failprimary on accent1.33:1 Failprimary on accent deep1.49:1 Failprimary on muted5.41:1 AAprimary on mist7.65:1 AAAprimary on paper8.21:1 AAAprimary on surface
accent7.91:1 AAAaccent on ink3.71:1 Failaccent on primarysame2.80:1 Failaccent on accent deep2.48:1 Failaccent on muted1.46:1 Failaccent on mist2.06:1 Failaccent on paper2.21:1 Failaccent on surface
accent deep2.83:1 Failaccent deep on ink1.33:1 Failaccent deep on primary2.80:1 Failaccent deep on accentsame1.13:1 Failaccent deep on muted4.07:1 Failaccent deep on mist5.76:1 AAaccent deep on paper6.19:1 AAaccent deep on surface
muted3.19:1 Failmuted on ink1.49:1 Failmuted on primary2.48:1 Failmuted on accent1.13:1 Failmuted on accent deepsame3.62:1 Failmuted on mist5.12:1 AAmuted on paper5.50:1 AAmuted on surface
mist11.53:1 AAAmist on ink5.41:1 AAmist on primary1.46:1 Failmist on accent4.07:1 Failmist on accent deep3.62:1 Failmist on mutedsame1.41:1 Failmist on paper1.52:1 Failmist on surface
paper16.32:1 AAApaper on ink7.65:1 AAApaper on primary2.06:1 Failpaper on accent5.76:1 AApaper on accent deep5.12:1 AApaper on muted1.41:1 Failpaper on mistsame1.07:1 Failpaper on surface
surface17.52:1 AAAsurface on ink8.21:1 AAAsurface on primary2.21:1 Failsurface on accent6.19:1 AAsurface on accent deep5.50:1 AAsurface on muted1.52:1 Failsurface on mist1.07:1 Failsurface on papersame

8 colors, 56 ordered pairs, 34 failing at 4.5:1 for normal text.

Measured on this page, in this browser
Network requests
·
Our own script
·

Was this tool useful?

Your palette never leaves your browser: this page doesn't send it to us or anywhere else. Once the page has loaded, you can disconnect and keep working. How we build tools
Requests: · listed · unlisted Script · Updated

Why one pair at a time is not enough

The two big contrast checkers take exactly two colors. That works when you've got two colors. A design system has eight or nine, and the interesting failures are never the pair you thought to check. They're the accent on the tile, the muted text on the card, the link color on the one surface you added last.

Here is a real one. Benchvale's own palette started with a brighter accent at #23A6B8. It looked right. Against the primary tile it measured 2.82:1, under the 3:1 floor that graphics and interface elements need, so the mark itself would have failed. Nothing would have told us without checking that specific pair, and that pair is one of 72 in a nine color palette. The fix was two colors instead of one: a bright accent for marks and a deeper #0E6B78 for anything that carries text.

That is the mistake this grid is built to catch, and it is the most common palette mistake there is: a color that passes as a graphic and fails as text. When a color in the paste can hit 3:1 against some partner and never 4.5:1 against any, its name is listed in the summary above the grid, so the graphics-only set is a list of colors rather than only a mode switch.

How to read the grid

Rows are the text color. Columns are the background. Each cell gives the ratio and the verdict.

Large text means 18.66px bold or 24px regular and above. Icons, borders, focus rings and chart strokes count as graphics and use the 3:1 floor.

What the ratio does not tell you

Contrast ratio is a luminance calculation. It says nothing about hue, so two colors can pass at 5:1 and still be indistinguishable to someone with deuteranopia. Run the palette through the color blindness simulator as well, and never let color be the only thing carrying meaning.

Questions

How do I check every color pair in a palette?

Paste your colors, one per line, as hex with an optional name after each. Rows are the text color and columns are the background, so every cell shows one pair's WCAG ratio and verdict. The default 8-color palette makes 56 ordered pairs. At 4.5:1 for normal text, 34 of them fail. The counts above the grid update as you type.

Can I use it to check chart colors?

Yes. Pick "Large text or graphics." Chart lines and bars that carry data are graphical objects under WCAG 2.2 success criterion 1.4.11, which asks for 3:1 against adjacent colors. Turn on "Use a separate background list" to test your series against the chart background alone. On white, warning yellow #F9AB00 scores 1.93:1 and fails, while info blue #1A73E8 passes at 4.51:1. Contrast can't tell you whether two series look alike to a color blind reader, so run them through the color blindness simulator too.

Why does my brand accent fail?

The ratio measures luminance only, so a bright, saturated color can still sit too close to a light background. Benchvale's own accent, #2FBFD0, scores 2.06:1 on #F5F7F9. That misses even the 3:1 floor for graphics. Our fix was a second, deeper shade for text: #0E6B78 scores 5.76:1 on the same background. Accent colors that fail as text walks through it.

How do I get the results out?

Copy results as text gives one line per pair, like ink on paper 16.32:1 AAA. Copy as CSS variables gives a :root block with one custom property per color, such as --ink:#131A22;. Copy share link copies a link that carries the palette after the #. For SCSS, JSON tokens or contrast notes inside the file, use palette to CSS.

Why does it stop at 14 colors?

Fourteen colors already make 182 ordered pairs, and a bigger grid gets hard to read. Colors past the 14th in each list are left out. The page tells you above the grid and in the status line how many were left out.

Does this send my colors anywhere?

No. Every ratio is calculated in this tab. Before any update to this page goes live, an automated check types into every box and presses every button, and blocks the update if what it typed turns up in a request. A share link carries your palette after the # in the address. Browsers don't send that part to a server.

Related tools

Once the palette survives the grid: the contrast checker is the same math for one pair when you already know which two colors to test. Export it to CSS variables and JSON tokens, which carries the contrast verdicts into the file as comments. Contrast is only half the check, so run it through the color blindness simulator as well: two colors can pass at 5:1 and still be the same gray to a large number of people. How to read a contrast ratio explains what the number itself means. And accent colors that fail as text is the specific failure this grid was built to catch, with our own numbers.

Maintained by Aaron Wilson
Published . Last updated . How the tools work and how we check them: how we build tools. Something wrong? Tell us.