Skip to content
RU
Scale
Density
Theme
Accent

Charts

Legend

The key to the colours of a chart. Obligatory at two series and more: without it colour reports nothing, and a chart with meaningless colour is a coloured-in picture.

The component
  • Render 18.2 s
  • Physics 11.5 s
  • Assets 8.1 s
  • Audio 4.2 s
Markup
<ul class="inst-legend">
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-1)"></span>Render <span class="inst-legend-value">18.2 s</span></li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-2)"></span>Physics <span class="inst-legend-value">11.5 s</span></li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-3)"></span>Assets <span class="inst-legend-value">8.1 s</span></li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-4)"></span>Audio <span class="inst-legend-value">4.2 s</span></li>
</ul>

Contract

A legend is a list. Series are enumerable, so this is a <ul>: a screen reader announces "a list of four items" before it begins to read them.

What Required Why
A <ul> and <li> yes Series are enumerable. A list announces their number before the reading
A --series on every swatch yes Otherwise every swatch is one colour — a legend with no legend
An order matching the chart yes The number of a series is a contract rather than an order of sorting
A quantity or a distinguishable label yes Colour has no right to be the only mark of a series

Accessibility

The structure A <ul> — the number of series is announced before the enumeration
Colour is not the only carrier A series has a label in words and, as a rule, a quantity. A legend where the series are told apart by the tone of the swatch alone works neither under colour blindness nor in black-and-white print
Contrast The swatch holds 3:1 against the surface: it is a load-bearing sign rather than decoration. The labels hold 4.5:1
Telling the series apart The lightness within the categorical palette differs: the series stay distinguishable when the hue disappears altogether
Type size --text-xs — 12.5px. The swatch is --size-dot, that is 6px: making it smaller is not allowed, it would stop reading as a colour
The order of reading The swatch comes before the label: a screen reader reads the label rather than an empty node, because the swatch has no text and is not announced

Anatomy

Class The work
inst-legend The <ul>. The markers and indents of a list are removed, and the items wrap
inst-legend-item The <li>. The swatch and the label in one line
inst-legend-swatch The mark of a series. It reads --series
inst-legend-value The quantity of a series. The full colour of the text and a medium weight

The mark of a series is a square rather than a circle: the circle in the library is taken by the state dot, and a round mark of a series would read as a status.

Variants

The colour of a series is assigned through --series inline — that is a channel of data: the number of a series comes with the data and cannot be known to static CSS. The styling of the swatch — the size, the radius, the position — is entirely in the library.

Example
  • Series 1
  • Series 2
  • Series 3
  • Series 4
Markup
<ul class="inst-legend">
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-1)"></span>Series 1</li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-2)"></span>Series 2</li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-3)"></span>Series 3</li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-4)"></span>Series 4</li>
</ul>

The order is part of the contract: the first series is always --chart-1, and the order in the legend has to match the order of the series on the chart. A legend sorted by quantity and a chart sorted by time give two different numberings of one and the same thing.

One series is not a category. If there is one series, --series is not set at all, and the default is --accent-mark rather than --chart-1. Categorical colour exists to tell series apart; at one series there is nothing to tell apart, and the first hue of the palette there would mean a category that does not exist.

--chart-1 comes into force when series no. 2 appears — and then --series is set explicitly on all the series, the first included.

Composition

With quantities

Example
  • Render 18.2 s
  • Physics 11.5 s
Markup
<ul class="inst-legend">
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-1)"></span>Render <span class="inst-legend-value">18.2 s</span></li>
  <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-2)"></span>Physics <span class="inst-legend-value">11.5 s</span></li>
</ul>

The quantity in a legend is a second carrier: it gives the exact number to somebody who does not tell the tones apart and makes the legend readable apart from the chart. That is precisely why inst-legend-value takes the full colour of the text and the label the muted one: what gets scanned is the numbers.

Under a chart in a card

In context
Time by module
  • Render 18.2 s
  • Physics 11.5 s
Markup
<div class="inst-card inst-stack inst-stack--tight">
  <div class="inst-card-title">Time by module</div>
  <svg class="inst-sparkline" viewBox="0 0 120 32" preserveAspectRatio="none" aria-hidden="true">
    <path class="inst-sparkline-line" d="M0,26 24,24 48,18 72,13 96,9 120,6"/>
  </svg>
  <ul class="inst-legend">
    <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-1)"></span>Render <span class="inst-legend-value">18.2 s</span></li>
    <li class="inst-legend-item"><span class="inst-legend-swatch" style="--series:var(--chart-2)"></span>Physics <span class="inst-legend-value">11.5 s</span></li>
  </ul>
</div>

The legend stands under the chart: above it, it pushes the data below the fold for the sake of what is read second.

API

Classes
NameWhat it does
class
inst-legendThe container list
inst-legend-itemAn item: a mark plus a label
inst-legend-swatchThe square mark of a series
inst-legend-valueThe quantity of a series
Tokens
NameValueWhere from
variable
--seriesThe receiver of the hue: the swatch of a legend reads it--accent-markthe application sets it
token
--chart-1The hue of series no. 1. The order is part of the contractlight-dark(oklch(0.520 0.150 292), oklch(0.700 0.130 292))one across every cell
--chart-2The hue of series no. 2. The order is part of the contractlight-dark(oklch(0.600 0.150 320), oklch(0.760 0.120 320))one across every cell
--chart-3The hue of series no. 3. The order is part of the contractlight-dark(oklch(0.550 0.140 355), oklch(0.720 0.120 355))one across every cell
--chart-4The hue of series no. 4. The order is part of the contractlight-dark(oklch(0.650 0.120 55), oklch(0.800 0.110 55))one across every cell
--chart-5The hue of series no. 5. The order is part of the contractlight-dark(oklch(0.580 0.130 115), oklch(0.740 0.120 115))one across every cell
--chart-6The hue of series no. 6. The order is part of the contractlight-dark(oklch(0.620 0.110 190), oklch(0.780 0.100 190))one across every cell
--size-dotThe side of the swatch6pxbase +4: scale
--radius-markThe rounding of the swatchvar(--radius-2xs)one across every cell
--text-xsThe size of the label0.78125rembase +4: scale
--space-3The gap between the swatch and the label6pxone across every cell
--gap-inlineThe gap between the itemsvar(--space-4)base +14: density · scale
--weight-mediumThe weight of the quantity600one across every cell

Why the kit works this way — the constitution · Open source under MIT, github.com/keshon/instrument