Why Now Playing Cards Come Out Grey

14 September 2026 · 7 min read

A now playing card is two colour decisions and a bit of layout. Both decisions are usually made by a single line of code, and both are wrong in ways you can measure in about a second each.

The first line takes the background from the average of the cover art. The second writes the text in white. Here is what each one actually does.

The average of a picture is a colour the picture does not contain

Take six equal bands of fully saturated hues — red, yellow, green, cyan, blue, magenta — and average every pixel. The answer is rgb(128, 128, 128). Saturation 0.0. Exactly grey, from an image with no grey in it anywhere.

That is not a quirk of one contrived picture. We measured three:

CoverAverageSaturationPresent in the artwork?
Six saturated hues128, 128, 1280.0 %No
Half red, half blue128, 0, 128100 %No
Green over near-black27, 103, 5258.5 %No

In all three the average colour was absent from the artwork. Half red over half blue averages to purple; there is no purple in the picture. Green over near-black averages to a darker, duller green than the green that is there.

And the pattern behind it is the part that matters: the more colourful the cover, the greyer its average, because opposing hues cancel. A bold sleeve gets a dull card. A monochrome sleeve gets a faithful one. That is precisely backwards from what anyone wants, and it is why so many of these cards look like the same washed-out rectangle regardless of what you fed them.

What to pick instead

The fix is to choose a colour that is genuinely in the picture. Quantise the cover into buckets — sixteen levels per channel is plenty — count the pixels in each, and take a populous one, weighted toward saturation so the sleeve's white paper and its black shadow do not win by sheer area.

On the six-hue cover that returns a red the picture actually contains. On a real sleeve it returns the colour you would have pointed at. The difference is one pass over a 96 × 96 thumbnail, which costs nothing.

White text fails on nearly two thirds of colours

Now the second line. Whatever colour came out of step one, the text goes on in white.

We sampled 636,056 colours across the sRGB cube and computed the WCAG contrast ratio of each against white and against black. 4.5:1 is the threshold for normal body text:

Text colourClears 4.5:1Clears 3.0:1
Always white36.4 %56.9 %
Always black65.3 %

A card that always writes in white is below the readability threshold on 63.6 % of the colours it could land on. Not unreadable in a dramatic way — it is legible on your own screen, at full size, when you already know what it says. It stops being legible on someone else's phone, in daylight, at thumbnail size, which is the only place it will ever actually be seen.

You never have to lose this one

Here is the part worth knowing, and it is stronger than a heuristic.

We scanned all 16,777,216 sRGB colours — the entire space, not a sample — and took, for each colour, the better of its contrast against white and against black. The worst case in the whole cube is 4.58:1, at rgb(207, 13, 204).

4.58 is above 4.5. There is no background colour on which both white and black text fail the threshold. Choosing between them per colour is not a rule of thumb that usually works; it is readable by construction, everywhere, and it costs one comparison:

function pickText(bg) {
    return contrast(bg, WHITE) >= contrast(bg, BLACK) ? WHITE : BLACK;
}

The measured figure is not an artefact of the scan, either. It matches the closed form exactly. Contrast against white falls as the background lightens and contrast against black rises, so the worst case sits where the two curves cross — at relative luminance √(1.05 × 0.05) − 0.05 = 0.1791, giving 1.05 / 0.2291 = 4.5826. The exhaustive scan and the algebra agree to four decimal places.

The third small thing

While we are here: track titles are long, and most generators let them run off the edge of the card or shrink the font until the artist line looks like a different design. A canvas can measure text — ctx.measureText(s).width — so the honest behaviour is to measure, ellipsise at the width available, and leave the type size alone. It is three lines and nobody does it.

What to do when you make one

Try it

Our now playing card maker does all of the above and shows you the second card beside yours — average colour, white text, the usual way — so the difference is visible rather than asserted. It reports the contrast ratio it achieved and the one white text would have given. Everything happens in your browser; the cover art is never uploaded.

If the cover is not square yet, the image resizer will get it there first, and the safe zone checker shows what a story's own interface will cover once you post the card.

FAQ

Why does averaging a cover give grey?

Because opposing hues cancel. Red and cyan average to grey, as do yellow and blue; a cover with a spread of saturated colours averages to something near the middle of the cube. Six equal bands of saturated hues gave exactly rgb(128, 128, 128), saturation 0.0.

Is 4.5:1 a real threshold or a guideline?

It is the WCAG AA threshold for normal-size body text, and it is a guideline in the sense that nothing enforces it on a social post. It is also the point below which text measurably costs people reading effort — more of them, and more effort, the further below it you go.

Does picking between white and black really never fail?

Not anywhere in sRGB. We scanned all 16,777,216 colours and the worst case for the better of the two is 4.5826:1, which matches the closed form: the curves cross at luminance sqrt(1.05 x 0.05) - 0.05 = 0.1791. Above 4.5, everywhere.

What about coloured text instead of white or black?

It can look better and it is harder to guarantee — a tinted text colour has to be checked against the background the same way, and most of the tints people reach for sit close to the background they were derived from. Black and white are the two colours whose worst case you can prove.

Why quantise rather than take the single most common pixel colour?

Because photographs and printed sleeves rarely repeat an exact RGB triple often enough for a single value to be meaningful. Quantising to sixteen levels per channel groups near-identical pixels together so the count means something, and weighting by saturation stops the paper white or the shadow black from winning on area alone.