Palette contrast grid

Six colors make thirty possible text and background pairs, and nobody tests thirty pairs by hand. Paste your palette to get all of them in one table, each with its ratio and level, plus a short list of the pairs you can use.

Put a comma or a new line between colors. Hex such as #1d3557, rgb(), hsl() and named colors such as teal are all accepted.

The math runs in your browser. No color is sent to us.

All pairs

Rows are text colors and columns are backgrounds. Select a cell to preview that pair.

AAA 7 or more AA 4.5 or more Large 3 or more, for headings only Fail below 3

Pairs that are safe to use

Why check a palette as a whole

Brand colors usually get picked side by side on a board, as swatches. They rarely get picked as pairs, with one written on top of the other. That comes back to bite later, when a developer needs a link color on the pale background, a caption on the accent panel and a label on the primary button, and chooses from the palette by eye.

The number of pairs grows fast. With n colors there are n × (n − 1) ways to put one on another, which makes 12 for four colors, 30 for six and 132 for twelve. Going through them one at a time is slow enough that nobody does it. A grid does it instantly, and it also shows you how the palette is built: which colors work as “ink”, which work as “paper” and which are only good for decoration.

Reading the grid

Each row is a text color and each column a background. A cell shows a sample “Aa” in those two colors, the WCAG contrast ratio cut to two decimals, and one of four labels:

LabelRatioUse for
AAA7 or moreAny text, including long articles
AA4.5 to 6.99Any text
Large3 to 4.49Headings of 24 px or more (18.66 px in bold), icons, borders of fields and buttons
Failbelow 3Decoration only, with no information in it

The ratio is the same whichever color is on top, so the table mirrors itself across the diagonal. We keep both halves because the samples don’t look the same. Dark on light and light on dark feel different even at an identical number. The Keep menu fades out every pair under the threshold you choose. Select a cell to open a larger preview with a heading, a paragraph, small type and a button. There’s also a link that sends the pair to the contrast ratio calculator, which can suggest a nearby shade that passes.

The three lists under the grid

Normal-size text
Up to eight pairs at 4.5:1 or more, strongest first. Each pair appears once, with the lighter color as the background, since that’s the common case.
Large text and headings only
Up to six pairs between 3:1 and 4.5:1. They’re tempting because they look fine in a mockup at 40 px. Put them in a paragraph and they fail.
Button sets
A button involves three colors and two tests. Its label has to reach 4.5:1 against the button, and the button itself has to reach 3:1 against the page, or people won’t see there’s a button at all. For each possible button color, the list gives the label with the highest contrast and the lightest page background that satisfies both.

If the first list comes up empty, the palette has no ink and paper pair. Add a near-black such as #1a1a1a or a near-white and the grid fills in.

Repairing a palette that falls short

Most palettes fall short the same way, with several mid-tone colors of similar lightness. Teal, coral, mustard and violet look nothing alike, and yet none of them can carry text on any of the others. Three additions fix almost every case:

  1. A dark neutral for body text. A deep version of the main brand hue does the job as well as black and still looks like the brand.
  2. A light neutral for page and card backgrounds, such as an off-white tinted with the brand hue.
  3. A darker step of the accent color for links and buttons. Lower the lightness until white text on it reaches 4.5:1, and keep the original accent for large shapes and illustrations.

Then write the result into your style guide as rules about pairs, for example “accent only on white, never under body text”. People make fewer mistakes with a list of allowed pairs than with a list of colors.

Input, sharing and limits

Separate colors with commas or line breaks. Hex with or without #, rgb(), hsl() and CSS color names all work. Duplicates are merged and anything after the twelfth color is ignored. The address bar always holds the current palette as ?c=1d3557,f1faee,…, so the link you copy reopens the same grid. Everything is computed in your browser.

A passing ratio guarantees a difference in lightness. It doesn’t guarantee that someone with a color vision deficiency can tell two colors apart when they’re used as a code, such as red for errors and green for success. Check those cases in the vision simulator.

Questions people ask

How many colors can I test at once?

From 2 to 12. Twelve colors produce 132 cells, and that’s about as many as a screen can show in a table you can still read. For a larger design system, test the text colors against the background colors in separate batches.

Why are two cells with the same ratio shown twice?

Contrast works both ways, so color A on B and B on A have the same ratio. The grid shows both because the rendered sample looks different, and because you usually look up a pair starting from the background you already have.

None of my brand colors pass on white. What should I do?

Keep the brand colors for large surfaces, illustrations and headings, where 3:1 is enough, and add a darker step of the main color for text and buttons. Open the failing pair in the contrast ratio calculator to get the nearest shade of the same hue that reaches 4.5:1.

Does the button need to contrast with the page, or only its label?

Both. The label follows the text rule (4.5:1 against the button color). The button’s visible boundary follows WCAG 1.4.11, which asks for 3:1 against adjacent colors, unless a border or another cue marks the button.

Can I paste colors straight from Figma or a CSS file?

Yes, paste the block as it is. The tool picks out hex codes, rgb() and hsl() values and color names, and lists anything it couldn’t read. Variable names and property names made of letters only may show up as unrecognized, which does no harm.