Ring

Determinate circular progress (Material CircularProgressIndicator equivalent): a conic-gradient donut cut to a 4px ring by a radial-gradient mask — no JS, no SVG. Progress is driven by the --value custom property (0..1) set inline, e.g. style="--value: 0.6". Fill is accent-bold over the track token; sizes 24 (.ring-sm) / 32 (default) / 48 (.ring-lg); optional absolute-centered 11px .ring-label. For indeterminate progress use .spinner; for linear progress use .progress.

Root: .ring on <div>, <span>

Examples

Example 1
60%
<div class="ring" style="--value: 0.6" role="progressbar" aria-valuenow="60" aria-label="Sprint completion"><span class="ring-label">60%</span></div>
Example 2
<span class="ring ring-sm" style="--value: 0.25" role="progressbar" aria-valuenow="25" aria-label="Upload progress"></span>
Example 3
100%
<div class="ring ring-lg ring-success" style="--value: 1" role="progressbar" aria-valuenow="100" aria-label="Import complete"><span class="ring-label">100%</span></div>

Contract

Variants & modifiers

ClassAxisRules
ring-smsizeoptional · exclusive
ring-lgsizeoptional · exclusive
ring-successstatusoptional · exclusive
ring-dangerstatusoptional · exclusive

Structure

SelectorRequiredDescription
.ring-labeloptionalOptional absolute-centered 11px semibold label (e.g. "60%"). It sits inside the donut hole — the gradient and mask live on ::before, so the label is never clipped. Best on the default and .ring-lg sizes; too cramped on .ring-sm.

Accessibility

OnAttributeLevelWhen
.ringrolerequired
.ringaria-valuenowrequired
.ringaria-labelrecommendedNo visible text labels the ring — give it aria-label (or aria-labelledby) naming what is progressing. role="progressbar" defaults aria-valuemin/aria-valuemax to 0/100, so express aria-valuenow on that scale (aria-valuenow="60" for --value: 0.6).

role="progressbar" and aria-valuenow are required — the visual arc is invisible to AT. Keep --value (0..1) and aria-valuenow (0..100) in sync; they are the same fact in two scales. Name the ring via aria-label/aria-labelledby. The .ring-label text is supplementary for sighted users and does not replace aria-valuenow. Status variants recolor the fill only (success/danger bold tokens) — pair them with visible text nearby, since color alone must not carry meaning.

Nesting

Allowed in:

  • inline content
  • table cells
  • .list-item-trailing
  • .card-body
  • stat rows

Never inside (or containing):

  • .ring
  • .btn