# Categorical series palette > Twelve services on one chart need twelve colors a person can tell apart. - Canonical: https://patterns.konigi.com/dashboards/categorical-series-palette - Group: Color - Level: context - Status: published - Updated: September 10, 2026 - Also called: series colors, qualitative palette --- ## Problem The chart has twelve lines. The legend has twelve swatches. Somewhere around the seventh, two of them are close enough that the viewer stops trusting the mapping and starts guessing. ## Solution A fixed ordered palette of qualitatively distinct hues, assigned deterministically, with a hard limit and a plan for what happens past it. The number people can actually distinguish is smaller than any palette suggests. Somewhere between six and eight is the practical ceiling for hues that must be matched against a legend across a distance. Past that, colour stops identifying and starts merely decorating, and the honest responses are to group into an "other", switch to small multiples, or use direct labelling instead of a key. Three requirements decide whether a palette survives contact with real data. **Distinguishable for colour vision deficiency.** Around one in twelve men and one in two hundred women have some form, most commonly red-green. A palette with red and green as adjacent series is unreadable for a meaningful slice of any audience, and this is the single most common failure. ColorBrewer's qualitative schemes remain the best starting point precisely because they were built around this constraint rather than around looking pleasant. **Distinguishable when small and thin.** A one-pixel line carries far less colour information than a legend swatch. Colours that separate cleanly as blocks converge as strokes, which is why palettes designed on filled shapes fail on line charts. **Stable assignment.** If colour is assigned by query result order, a series that disappears shifts every colour after it, and the viewer's learned mapping breaks silently. Assignment should hash from the series name or come from an explicit override, so `checkout` is the same colour today and next week and on the other dashboard. WCAG's rule applies here as everywhere: colour cannot be the only carrier. On a dense chart the practical answer is direct labelling at the line's end, which removes the legend round-trip entirely. ## Use when Several series share one chart, the categories are unordered, and viewers need to track individual series across panels or over time. ## Don't use when The categories have an order or a magnitude, where a sequential ramp encodes more. Or when the count is beyond what anyone can distinguish, which is the case more often than palettes admit. ## Trade-offs Every colour spent on a series is unavailable for status, which is the collision that quietly ruins monitoring pages: a chart whose series happen to be red and green sitting beside tiles where red and green mean failure and health. Palettes look different on dark and light themes and usually need separate tuning. Brand palettes are rarely built for data and frequently offer three hues and a lot of tints. And the more series a chart carries, the more the palette is papering over a chart that should have been split. ## Checklist - How many series can appear here at most, and does the palette cover that? - Do any two adjacent-in-value series share similar hues? - Does the palette survive the common colour vision deficiencies? - Do the colours separate as thin lines, not just as legend swatches? - Is colour assigned deterministically from the series name, or by result order? - Does the same category get the same colour on every panel and dashboard? - Do any series colours collide with the status palette? - Is there a defined behaviour past the palette's limit? - Would direct labelling remove the need for a legend entirely? - Does the palette have a tested dark-theme variant? ## Compare **ColorBrewer** is still the reference, because Cynthia Brewer's schemes were designed against colourblind-safe, print-safe and photocopy-safe criteria rather than aesthetics, and its qualitative sets remain the best default anyone can adopt in an afternoon. **Grafana** ships a classic palette assigned by series order in many panels, with per-series overrides available, which means dashboards drift in colour meaning as queries change unless someone pins them. **Datadog** hashes series colours from tag values so the same tag keeps its colour across widgets, which is the behaviour worth copying. **Observable Plot and D3** default to well-researched schemes and make the limit explicit by forcing a decision when the category count exceeds the scheme. ## Related Dark-first data palette covers the theme problem this pattern inherits. Legend and series toggle is the mechanism that makes a large palette bearable. Semantic status color is the palette this one must not collide with. Small multiples is the answer once the series count outruns the colours. Sequential and diverging scales is the right choice when the categories turn out to have an order. ## Examples ### Cloudflare Radar (Cloudflare) A public dashboard with no account, no filters worth the name, and an audience of journalists. Designed for people who will read one number and leave. **Worldwide Overview, dark** — captured September 11, 2026, Public site, signed out; no version string exposed. public, medium density, dark theme, desktop-web. The same page and the same figures, captured minutes apart on the other ground. Only the promotional strip at the top differs, and it rotates. Radar is worth the pair because it does not restate its palette in the dark: the hues are the same, and what changes is how much light each one carries against what is behind it. In the traffic chart the dark blue that reads as the heavier of the two series on white is now the one closest to the background, and the pale blue that was the quiet one carries the chart. The stacked attack bars show the milder version of the same thing—WAF still holds the largest share and still looks it, but the lighter segment beside it pulls more attention than its 39.7% has earned. The red on the browser deltas is the one colour that reads the same on both grounds, which is what you want from a colour carrying meaning and what a colour carrying identity cannot promise. Hotspots in this capture: - [Dark-first data palette](https://patterns.konigi.com/dashboards/dark-first-data-palette) — Same two hues as the light capture. On charcoal the darker series is the one fighting the ground. - [Categorical series palette](https://patterns.konigi.com/dashboards/categorical-series-palette) *(this pattern)* — Four categories, four fixed hues, held across both grounds. Which one dominates the eye is not held. - [Delta indicator](https://patterns.konigi.com/dashboards/delta-indicator) — The one colour that reads the same on both grounds, because it is carrying meaning rather than identity. ### Honeycomb Query-first; heatmaps and BubbleUp replace the dashboard-of-panels model with draw-a-region cross-filtering. **Trace / cart checkout** — captured September 11, 2026, Honeycomb sandbox, public dataset (signed out). analytical, dense density, light theme, desktop-web. Seventy-one spans over 3.288 seconds for one checkout, and the shape gives the answer away before you read a single duration. Two thirds of the way down, getDiscounts runs for 2.576s—more than three quarters of the whole request —and underneath it nine visible SELECT spans step down and to the right in a staircase, each starting after the last one finished. The badge on the parent says 19. Nineteen queries in a loop, run one at a time, and the waterfall says so by its outline rather than by any number. That is the shape worth learning: siblings overlapping means concurrency, siblings in a staircase means something that should have been one query. The panel top right is the other good idea here—it plots the distribution of this span's duration across the whole dataset and marks where this particular trace fell, so you can see whether you are looking at a normal request or the tail before you start optimising. Hotspots in this capture: - [Trace waterfall](https://patterns.konigi.com/dashboards/trace-waterfall) — Indentation is causality, length is duration, horizontal position is when it started. Six levels deep here. - [Trace waterfall](https://patterns.konigi.com/dashboards/trace-waterfall) — The staircase: nineteen SELECTs one after another inside getDiscounts. Batch the query, don't add a machine. - [Percentile summary](https://patterns.konigi.com/dashboards/percentile-summary) — This span's duration against the whole distribution, with this trace marked—so you know if you're looking at the tail. - [Detail on demand](https://patterns.konigi.com/dashboards/detail-on-demand) — Selecting a span fills the right pane with its fields. The waterfall never moves while you read. - [Overview then detail](https://patterns.konigi.com/dashboards/overview-then-detail) — A minimap of all 71 spans above the list, so the shape of the whole trace is visible before you scroll it. - [Categorical series palette](https://patterns.konigi.com/dashboards/categorical-series-palette) *(this pattern)* — Five services, five hues, and the name in a column beside every one. Colour is never carrying it alone. ### Tableau Public (Salesforce) Thousands of dashboards made by people who are not designers, published without a review step. The best available sample of what the pattern language looks like in the wild. **Energy flows in the Regional scenario** — captured September 11, 2026, Tableau Public embed view; workbook published by Chia Yu Lin. analytical, medium density, light theme, desktop-web. A Sankey doing the job it was invented for, published by an analyst rather than designed by Tableau. The entry argues that the form comes from engineering, where what enters a node leaves it, and that conservation is what makes band width readable as quantity—and that product analytics breaks it because people leave and nothing accounts for them. Here conservation holds and is stated: primary supply 546 TWh at the bottom left, final demand 476 TWh at the bottom right, and the missing 70 TWh has its own destination node called Conversion losses. Nothing disappears off the edge of the diagram. Colour is doing identity rather than status—blue for electricity, green for hydrogen, teal for biomass, orange for heat—and it stays consistent across all three columns, so a carrier can be traced from supply to end use without a legend. The one oddity is that the author has exposed the layout parameters as live controls, including a squish ratio printed to nine decimal places. Hotspots in this capture: - [Sankey and path](https://patterns.konigi.com/dashboards/sankey-and-path) — Three columns of nodes, link width as volume, and crossings kept to the few places where a carrier genuinely switches rank. - [Sankey and path](https://patterns.konigi.com/dashboards/sankey-and-path) — Conversion losses as an explicit destination. This is the node product analytics leaves out, and the reason its widths stop adding up. - [Ratio and rate](https://patterns.konigi.com/dashboards/ratio-and-rate) — 546 TWh in, 476 TWh out, both stated. The diagram's own arithmetic is checkable from the page. - [Categorical series palette](https://patterns.konigi.com/dashboards/categorical-series-palette) *(this pattern)* — Five carriers, five hues, held constant across every column so a band can be followed end to end. - [Dashboard builder](https://patterns.konigi.com/dashboards/dashboard-builder) — Curve type, whitespace and squish ratio exposed as reader-facing controls. The last one reads 0.484057971. ### Grafana (Grafana Labs) The reference implementation for panel grids, template variables, and stat panels; most other tools are defined by how they differ from it. **Examples / Dashboard Variables** — captured September 10, 2026, Grafana Play (signed out; no version string exposed). analytical, medium density, dark theme, desktop-web. Six selectors across the top and the page is unusually honest about what they cost. The middle panel says there is a hidden variable called bestfood, currently set to pizza, which has no control anywhere on screen—state affecting the page that a viewer cannot see or change. The overview panel says that setting Instance and then changing the Prometheus source will clear your selection, because the two variables are chained and the second one invalidates the first. Both of those are correct behaviour and both are the reason parameterised pages get distrusted. What the top row gets right is the display: Instance and CPU Usage Type show their selected values as chips with an × rather than as a count, so what is filtering the page is legible without opening anything. Hotspots in this capture: - [Template variable](https://patterns.konigi.com/dashboards/template-variable) — Six selectors bound to every panel's query, with the chosen values carried in the URL. - [Filter bar](https://patterns.konigi.com/dashboards/filter-bar) — Values as removable chips rather than a dropdown saying Instance (3). - [Explain this metric](https://patterns.konigi.com/dashboards/explain-this-metric) — Names a hidden variable set to pizza. Prose is doing the work a control should. - [Categorical series palette](https://patterns.konigi.com/dashboards/categorical-series-palette) *(this pattern)* — Twelve-plus hostnames differing only in the middle digits, with twelve-plus colours to match. - [Data table](https://patterns.konigi.com/dashboards/data-table) — Four columns visible, the fourth cut mid-word, with no horizontal scroll offered. ## Related patterns - [Dark-first data palette](https://patterns.konigi.com/dashboards/dark-first-data-palette) — Ops dashboards live on dark screens all night and the chart colors have to survive it. - [Legend and series toggle](https://patterns.konigi.com/dashboards/legend-and-series-toggle) — Too many series on one chart; the viewer needs to isolate the ones that matter without leaving the chart. - [Semantic status color](https://patterns.konigi.com/dashboards/semantic-status-color) — State has to be readable before the number is. - [Small multiples](https://patterns.konigi.com/dashboards/small-multiples) — Many series would tangle on one chart; the viewer needs them on identical axes side by side. - [Sequential and diverging scales](https://patterns.konigi.com/dashboards/sequential-and-diverging-scales) — Magnitude and direction need encoding in color, and the wrong ramp lies. ## Sources - [ColorBrewer](https://colorbrewer2.org/) - [Colour Blind Awareness, About colour blindness](https://www.colourblindawareness.org/colour-blindness/) - [W3C, WCAG 2.2—Use of Color](https://www.w3.org/WAI/WCAG22/Understanding/use-of-color.html) --- Screenshots on patterns.konigi.com are reproduced for commentary and criticism. Product names and marks belong to their owners.