The arithmetic nobody does
A palette is signed off one color at a time. Here is the brand violet, here is the neutral ramp, here is the red for errors. Each one gets looked at on its own, against white, and approved.
Then it ships, and it gets used two at a time. Every combination someone might reasonably reach for is a color pair that either works or does not, and the count grows quadratically.
| Colors in the palette | Possible pairs |
|---|---|
| 4 | 6 |
| 6 | 15 |
| 8 | 28 |
| 12 | 66 |
| 16 | 120 |
The formula is n(n-1)/2. Sixteen colors, which is a small design system, is a hundred and twenty combinations. Nobody has checked a hundred and twenty combinations. Most teams have checked the three or four that appear in the mockup.
Most of those pairs do not matter
This is where a matrix of every ratio can mislead as easily as it helps. A grid full of red cells looks alarming, and most of the red is combinations nobody would ever ship.
Two of your text colors failing against each other is not a finding. They are both text; they never touch. The pairs that matter are the ones where one color is type and the other is the surface underneath it.
- —Every text color, on every surface it could land on. This includes the tinted notice backgrounds people forget are surfaces.
- —White or near-white, on every color you use as a filled button.
- —Your muted or secondary text, on every surface. This is where the real failures live, because muted is chosen to recede and recedes slightly too far.
- —Semantic colors on the surfaces they appear on: the error red on the error tint, not the error red on the brand violet.
The token that is not the color it looks like
Real palettes are full of translucent tokens. A hairline rule at rgba(0, 0, 0, 0.1), a hover state at ten percent of the brand color, an overlay at sixty percent black.
Measure one of those as its base color and the answer is not merely wrong, it is inverted. Read as pure black, a ten percent black rule scores 21:1 and looks like the safest color you own. On a white page it composites to a very light grey and is close to the least contrasty thing in the file.
Alpha compositing has to happen before measurement, against whatever the token actually sits on. This is the single commonest reason a palette that was checked by hand still fails in a browser, and it is why the scanner reads painted colors rather than declared ones.
Findings need names, not hex codes
A report that says #71717a on #6d3bee fails at 1.24:1 is arithmetic. A report that says muted on violet fails at 1.24:1 is a task, because you know where that lives in your stylesheet.
Your file already has the names. Anything that makes you retype the colors by hand has thrown away the half of the information that made the finding actionable, and introduced a chance to mistype a digit on the way.
Palette matrixPaste the CSS variables or Tailwind config you already have. Every combination is checked, names are kept, and translucent tokens are composited rather than flattened.When it is one combination, not the set
Half the time the question is not the whole palette. It is one pairing somebody is arguing about in a review, and what you want is the number and the nearest color that would settle it.
Contrast checkerTwo colors, every threshold, and the nearest passing shade with your hue held exactly.A clean palette is not a clean page
Worth saying plainly, because it is the mistake that follows a green matrix. Every pair in your palette passing does not mean your site passes.
- —Colors arrive that are not in the palette at all: a hard-coded hex in one component, an embedded SVG, a third-party widget, an email template someone pasted in.
- —Opacity is applied at the point of use rather than in the token, so a passing color becomes a failing one in situ.
- —Text lands on an image or a gradient, where no single background color exists and no ratio is honest.
- —A color that passes at 16px is used at 13px, where the same ratio is no longer enough.
The palette is the right place to start, because fixing a token fixes every use of it at once. It is just not the place to stop.
Common questions
- How many color combinations does a palette have?
- A palette of n colors has n(n-1)/2 possible pairs. Eight colors make twenty-eight combinations, twelve make sixty-six, and sixteen make a hundred and twenty. Contrast is symmetric, so a pair only needs checking in one direction.
- Which pairs in a palette actually need checking?
- The ones where one color is text and the other is a surface it can land on. Two background colors failing against each other is arithmetic rather than a finding, since they never appear together as type on a surface.
- Why does my palette pass but my site still fail?
- Because pages contain colors the palette does not: hard-coded values, third-party widgets, embedded SVG, and opacity applied at the point of use. Text over images and gradients has no single background color at all, so no ratio for it is honest.
- How do I check a translucent color like rgba(0,0,0,0.1)?
- Composite it over the surface it will sit on, then measure the result. Measuring the base color instead inverts the answer: ten percent black reads as 21:1 against white when the composited color is close to the lowest contrast in the palette.