Designing a data visualization palette

Chart colors have a harder job than interface colors. They have to be distinguishable at small sizes, in any order, for everyone.

↑ Click any of these to repaint the entire site with it.

Interface color has a small number of jobs and plenty of space to do them in. Chart color has more jobs and much less space: a categorical series might be a two-pixel line or a four-pixel dot, seen alongside five other series, at whatever size the container happens to be.

The constraints are different enough that a good UI palette usually makes a bad chart palette.

Three kinds of scale#

Categorical. Distinct things with no order — countries, products, teams. Every color must be distinguishable from every other, including at small sizes and for color vision deficiency. Six is about the practical limit; past eight, add direct labels or stop using color.

Sequential. One quantity, low to high. A single hue varying in lightness, or two adjacent hues. The critical property is that lightness must be monotonic — every step measurably lighter or darker than the last — because that is what makes the ordering readable.

Diverging. A quantity with a meaningful midpoint — profit and loss, above and below average. Two hues meeting at a light neutral. The neutral must genuinely be neutral, or the midpoint appears to be somewhere it is not.

Using the wrong kind is the most common chart color error. A categorical palette on a sequential quantity destroys the ordering; a sequential ramp on categories implies a ranking that does not exist.

Categorical: what actually works#

The requirements compound:

  1. Distinguishable from each other by hue and lightness
  2. Distinguishable under protanopia and deuteranopia
  3. Readable against both light and dark chart backgrounds
  4. Not so saturated that six of them together are exhausting

That last one is why default palettes from charting libraries look so aggressive — they optimize for distinguishability alone and end up at maximum chroma everywhere.

A workable approach: pick hues spaced widely on the OKLCH circle, then vary lightness deliberately so no two series share both properties. If two colors differ in hue but not lightness, they will merge for someone.

Note that these are not all the same lightness. That is the point.

The rainbow problem#

Rainbow and jet color maps are still everywhere in scientific visualization and they are actively misleading.

Lightness in a rainbow scale is not monotonic — it peaks at yellow and drops at both ends. That creates apparent boundaries at the yellow band that correspond to nothing in the data, and hides real structure in the regions where lightness happens to be flat.

Use a perceptually uniform sequential map instead. Viridis, magma and their relatives were designed precisely to have monotonic lightness. They look less exciting and they show the data.

The fastest test of a chart palette: convert it to greyscale.

If the series are still distinguishable, the palette is robust — it will survive color blindness, bad projectors, photocopies and small sizes. If everything collapses to the same gray, hue was doing all the work and the chart depends on ideal viewing conditions.

This single check catches most chart color problems, and it takes ten seconds.

The things that beat color#

Direct labels. A label at the end of each line removes the legend, removes the color dependency and removes the eye movement between legend and chart. It is better on every axis and it is used far too rarely.

Line style. Dashes and dots distinguish series with no color at all.

Emphasis over enumeration. Most charts have one series that matters and several for context. Color the important one; make the rest gray. This is almost always a better chart than six equally weighted colors, and it sidesteps the entire palette problem.