Skip to main content
Gremorie
Chart

Categorical

Five hues for series identity in nominal data - regions, departments, types.

Categorical is the scheme for nominal data without order - when you compare magnitudes across categories that have no "greater/smaller" relationship. Five hues, one primitive family per slot, the same family in light and dark so a series keeps its colour when the mode flips - only the step changes (500 light, 600 dark).

The set is measured, not eyeballed: every pair is checked for lightness band, chroma floor, separation under simulated protanopia and deuteranopia, separation for full colour vision, and contrast against the chart surface.

--chart-cat-1
--chart-cat-2
--chart-cat-3
--chart-cat-4
--chart-cat-5

Tokens

AmostraTokenPrimitivo
--chart-cat-1blue-500
--chart-cat-2amber-500
--chart-cat-3green-500
--chart-cat-4cyan-500
--chart-cat-5pink-500

When to use

  • Bar charts comparing regions / products / channels - the comparison is "which is bigger", not "which comes first".
  • Multi-series line charts - different metrics over the same X axis.
  • Pie or donut with up to 5 slices - beyond that the reading collapses; switch to bars.
  • Scatter plots where color encodes the category.

Why five, and what happens past it

Five is not a design preference - it is what these primitive ramps separate. A sixth slot collapses against one of the five under colour-vision deficiency whichever family it comes from: fuchsia lands on blue at ΔE 5.0 under protanopia, purple at ΔE 0.7 under the commoner deuteranopia, and sky fails even for full colour vision against cyan. Adding one would hand two different series the same read.

Notion's categorical scheme stops at five and repeats, for the same reason.

Past the fifth series the scale repeats. Two series then share a colour, which is a real cost and a deliberate one: a repeat is easier to work around than a generated hue that collides with a neighbour, and more honest than a silent neutral.

If you need more than five series, the chart is usually the problem:

  1. Group the rest into "Other".
  2. Small multiples - one series per mini chart.
  3. A different visualization - heatmap, parallel coordinates.

Not themeable, on purpose

A brand palette is for chrome. Series identity needs hues that separate, and a themed override turns this into a single-hue ramp - which encodes order, not identity, leaving two series to differ only in lightness. The scale is the same under every theme.

When not to use

  • The data has an inherent order (intensity, severity) - use Sequential.
  • The data carries state semantics (good/bad/neutral) - use Status.
  • You have one highlighted series plus background series - use Comparison.

Anti-patterns

Using Categorical for more than 8 series. The colors start blending together and the reading collapses. Refactor to one of the three alternatives above.

Mixing Categorical with Status in the same chart ("one of the series is red because it is the error metric"). This pollutes the reading - the user will infer meaning in every color.

Usage example

import { Line, LineChart } from 'recharts';

const config = {
  receita: { label: 'Receita', color: 'var(--color-chart-cat-1)' },
  custo: { label: 'Custo', color: 'var(--color-chart-cat-2)' },
  lucro: { label: 'Lucro', color: 'var(--color-chart-cat-3)' },
} satisfies ChartConfig;

<LineChart data={data}>
  <Line dataKey="receita" stroke="var(--color-chart-cat-1)" />
  <Line dataKey="custo" stroke="var(--color-chart-cat-2)" />
  <Line dataKey="lucro" stroke="var(--color-chart-cat-3)" />
</LineChart>;

On this page