Skip to main content

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.

Visitors this month

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.

Visitors by device, this month

1,830 visitors

  • Desktop 1,260
  • Mobile 570

Known issues

None known.

Code

Copy the markup

Bundler
import "@luz-ds/catalog/components/ring.css";
HTML
<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:

HTML
<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:

HTML
<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

OptionEffect
--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

Do Say the goal in the label, so the figure reads whole without the ring.
Don't Leave the goal to the ring: “1,260” alone does not say of how many.

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.

PartColour on backgroundLightDarkHigh contrastNeeds
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.

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.