Catalog · Charts
Ring
Shows one value over a goal, or the shares of a total, as half a ring over the figure that says it.
Fits best: app — a panel that shows progress to a goal or how one total is split
Example
One value over a goal: visitors this month against a goal of 2,000. The figures are sample data, yours to replace.
1,260 of 2,000 visitors
Stacked
Two series that add up to a total, with a legend: visitors this month by device. With no --max, the series fill the half ring.
1,830 visitors
- Desktop 1,260
- Mobile 570
Known issues
None known.
Code
Copy the markup
import "@luz-ds/catalog/components/ring.css";
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@luz-ds/catalog@0.3.0/dist/components/ring.min.css" integrity="sha384-YaRd4u10aQ2xYJEzSk0IBieFbMmJkBTRW8kCchIj7ejPMF7CLvBpdCPmju18ffH5" crossorigin="anonymous">
Link components/ring.css of @luz-ds/catalog after luz.css. One value over a goal:
<figure class="luz-ring" style="--v1: 1260; --max: 2000">
<figcaption>Visitors this month</figcaption>
<p class="luz-ring__value">
<span class="luz-ring__figure">1,260</span>
<span class="luz-ring__label">of 2,000 visitors</span>
</p>
</figure>
Series that add up to a total, with a legend:
<figure class="luz-ring" style="--v1: 1260; --v2: 570">
<figcaption>Visitors by device, this month</figcaption>
<p class="luz-ring__value">
<span class="luz-ring__figure">1,830</span>
<span class="luz-ring__label">visitors</span>
</p>
<ul class="luz-ring__legend">
<li class="luz-ring__item"><span class="luz-ring__name">Desktop</span> <span class="luz-ring__figure">1,260</span></li>
<li class="luz-ring__item"><span class="luz-ring__name">Mobile</span> <span class="luz-ring__figure">570</span></li>
</ul>
</figure>
Variants and options
| Option | Effect |
|---|---|
--v1 | The first series, a plain number (1260, not 1,260). --v2 to --v4 add up to three more, in the order of the legend |
--max | The goal. Without it, or when the series add up to more, they fill the ring |
--luz-ring-size | The widest the half ring gets, 18rem by default; it shrinks to its box |
--luz-ring-color | The colour of the first series, such as var(--luz-chart-5); the others keep --luz-chart-2 to --luz-chart-4 |
How it works
The text is the data: the caption, the figure and its label, and for series a legend. The ring is a picture of it, drawn by the two pseudo-elements of the paragraph (the track and the series, each cut to a band by a mask), so assistive technology never meets it.
Each series takes its --v over --max, or over the sum of the values with no --max, and --luz-chart-1 to --luz-chart-4 in order, the colours of the legend's swatches. It runs from the left, clockwise, in every language, as a clock does. The inline style sets only numbers; with a strict style-src, set them in a rule of your own.
The figure is a size container: under 14em the text goes under the arc, not inside it. On paper the ring is left out and the text prints.
Without JavaScript
It needs none. Without the stylesheet it reads as its caption, the figure and its label, and the legend; there is no ring.
Keyboard and ARIA
Nothing takes focus and there is no ARIA: a screen reader reads the caption, the figure, its label and the legend, in that order. Write the goal into the label (“of 2,000 visitors”): the ring alone does not say it.
In forced colors the track is the background, so the gaps between series are too; the series and the swatches take the same system colours, and each swatch shows its series number.
Contrast and focus are in the Design tab.
Design
When to use
Use it in a panel for how far one value is to its goal (a quota, a budget, a storage limit), or how a total splits in two or three parts, when the figure is the point and the ring a glance at it.
When not to use
Do not use it to compare values (use a bar list or a column chart: a length reads better than an angle), for more than four series (use a stacked bar), or for a value in running text or a form (use a meter).
Do and don't
Writing the content
Name what is counted and the period in the caption (“Visitors this month”), write the figure as it is read, with its separators, and say the goal or the unit in the label. Keep legend names to a word or two.
Contrast and focus
Each series is a chart colour on the surface and on the track; the track is decorative, because the figure says the value.
| 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 1 on a card | --luz-chart-1 on --luz-surface | 5.9:1 | 7.2:1 | 14.1:1 | 3:1 |
Series 2 on a card | --luz-chart-2 on --luz-surface | 5.6:1 | 8.2:1 | 9.3:1 | 3:1 |
Series 1 on the track | --luz-chart-1 on --luz-chart-track | 3.4:1 | 3.8:1 | 6.8:1 | 3:1 |
Series 2 on the track | --luz-chart-2 on --luz-chart-track | 3.2:1 | 4.4:1 | 4.4: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 3 on the track | --luz-chart-3 on --luz-chart-track | 5.9:1 | 5.3:1 | 5.2: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 4 on the track | --luz-chart-4 on --luz-chart-track | 6.0:1 | 3.0:1 | 3.2:1 | 3:1 |
Figure | --luz-text-primary on --luz-surface-page | 15.8:1 | 15.1:1 | 21.0:1 | 4.5:1 |
Label and name | --luz-text-secondary on --luz-surface-page | 6.2:1 | 7.5:1 | 19.3: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.
- Focus: nothing takes it.
- Not colour alone: every value is in text, a gap of the track separates two series, and the legend is in the order of the ring.
Tokens it uses
The 18 tokens that components/ring.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-track,--luz-text-secondary- Spacing and sizing
--luz-space-2xs,--luz-space-4xl,--luz-space-md,--luz-space-sm,--luz-space-xs- Typography
--luz-font-heading,--luz-font-mono,--luz-font-sans,--luz-text-2xl,--luz-text-sm,--luz-text-xs- Radius
--luz-radius-sm
Keyboard and ARIA are in the Code tab.