Catalog · Charts
Stacked bar
Shows the shares of a whole in one bar, with a legend that says each name and figure in text.
Fits best: app — a page that shows how a whole is split: statuses, sources, a budget
Example
How this week's parcels ended: the bar shows the shares, the legend says them.
Known issues
None known.
Code
Copy the markup
import "@luz-ds/catalog/components/stacked-bar.css";
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/stacked-bar.min.css" integrity="sha384-EawyC0MeY43Ls6Vyna5Wo6tQtAJbKY4vu6C6J930w4veLj3B1yFokJZyIu5APjrV" crossorigin="anonymous">
A stylesheet of @luz-ds/catalog: link components/stacked-bar.css after luz.css.
<figure class="luz-stacked-bar">
<figcaption>Parcels by status, this week</figcaption>
<div class="luz-stacked-bar__bar" aria-hidden="true">
<span class="luz-stacked-bar__part" style="--v: 62"></span>
<span class="luz-stacked-bar__part" style="--v: 28"></span>
<span class="luz-stacked-bar__part" style="--v: 10"></span>
</div>
<ul class="luz-stacked-bar__legend">
<li class="luz-stacked-bar__item"><span class="luz-stacked-bar__name">Delivered</span> <span class="luz-stacked-bar__figure">62 %</span></li>
<li class="luz-stacked-bar__item"><span class="luz-stacked-bar__name">In transit</span> <span class="luz-stacked-bar__figure">28 %</span></li>
<li class="luz-stacked-bar__item"><span class="luz-stacked-bar__name">Delayed</span> <span class="luz-stacked-bar__figure">10 %</span></li>
</ul>
</figure>
Variants and options
| Option | Effect |
|---|---|
--v | On each part, its weight: the bar always fills its width and a part takes its --v of the sum, so 62, 21 and 9 work as well as .62, .21 and .09 |
--luz-stacked-bar-color | Another chart colour for a part and its item, such as var(--luz-chart-4) |
--luz-stacked-bar-h | The height of the bar |
How it works
A figure with two lists of the same shares in the same order. The legend is the data: a name and a figure in text for each share, with a swatch in its colour. The bar is a picture of it, a row of parts that take the width in proportion to their --v, with the surface showing through a thin gap between them.
The series take --luz-chart-1 to --luz-chart-6 in the order of the markup, so up to six shares keep their own colour. Put the largest first and group the smallest as “Other”. The inline style sets only --v. With a strict style-src, set it in a rule of your own.
Without JavaScript
It needs none. Without the stylesheet the figure reads as its caption and the legend, a list of names and figures; the bar is empty.
Keyboard and ARIA
Nothing takes focus. The caption and the legend are text: hide the bar with aria-hidden="true", as in the example.
In forced colors the parts and the swatches of the legend carry the same number, so a part is matched to its item by number. The number may not fit in a very narrow part; the legend is in the same order as the bar.
Contrast and focus are in the Design tab.
Design
When to use
Use it to show how a whole is split, when the parts add up to one total: statuses, sources, shares of a budget.
When not to use
Do not use it to compare many values (use a bar list or a column chart), for more than six shares, or for one share (use a meter).
Do and don't
Writing the content
Name the whole and the period in the caption (“Parcels by status, this week”), keep each name to a word or two, and write every figure with its unit. The data and the labels are yours: the component only draws them.
Contrast and focus
Each series is a chart colour on the surface; the six are also told apart from each other by hue and lightness, checked in every mode.
| Part | Colour on background | Light | Dark | High contrast | Needs |
|---|---|---|---|---|---|
Series 1 on the page | --luz-chart-1 on --luz-surface-page | 5.6:1 | 7.7:1 | 14.1:1 | 3:1 |
Series 2 on the page | --luz-chart-2 on --luz-surface-page | 5.3:1 | 8.9:1 | 9.3:1 | 3:1 |
Series 3 on the page | --luz-chart-3 on --luz-surface-page | 9.6:1 | 10.6:1 | 10.9:1 | 3:1 |
Series 4 on the page | --luz-chart-4 on --luz-surface-page | 9.8:1 | 6.1:1 | 6.6:1 | 3:1 |
Series 5 on the page | --luz-chart-5 on --luz-surface-page | 3.9:1 | 5.0:1 | 6.2:1 | 3:1 |
Series 6 on the page | --luz-chart-6 on --luz-surface-page | 3.7:1 | 5.4:1 | 14.7:1 | 3:1 |
Series 1 on a card | --luz-chart-1 on --luz-surface | 5.9:1 | 7.2:1 | 14.1:1 | 3:1 |
Name | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3:1 | 4.5:1 |
Figure | --luz-text-primary on --luz-surface-page | 15.8:1 | 15.1:1 | 21.0:1 | 4.5:1 |
Measured from the token values of each mode, rounded down. Needs is the WCAG 2.2 AA minimum: 4.5:1 for text, 3:1 for focus rings, borders and icons; a quiet decorative part keeps 2:1 against what it is drawn on.
- Focus: nothing takes it.
- Not colour alone: every share has its name and figure in text, a gap separates the parts, and in forced colors each part and its item show the same number.
Tokens it uses
The 17 tokens that components/stacked-bar.css reads, by family. Each family links to its page, with the values in every mode. In Figma they are variables with the same names: see Tokens in Figma.
- Color
--luz-chart-1,--luz-chart-2,--luz-chart-3,--luz-chart-4,--luz-chart-5,--luz-chart-6,--luz-text-secondary- Spacing and sizing
--luz-space-2xs,--luz-space-3xs,--luz-space-md,--luz-space-sm,--luz-space-xs- Typography
--luz-font-mono,--luz-font-sans,--luz-text-sm,--luz-text-xs- Radius
--luz-radius-sm
Keyboard and ARIA are in the Code tab.