Skip to content

ExpressiveCSS

Browse documentation

Preloader

Activity and progress. The HTML is the indicator.

View as Markdown

In forced-colors mode, native and custom progress use system colors. Empty linear tracks get an outline, and circular indicators keep their value segments. Under reduced motion, the indicators still show static feedback. Browser emulation checks do not replace a review in Windows high contrast or with a screen reader.

Custom linear progress fills from the left in LTR and from the right in RTL. Indeterminate motion and the static reduced-motion fill follow the inherited direction, including nested overrides. This does not change native determinate progress or circular indicators.

Show a progress indicator when content takes a while to load. A linear bar is a native <progress>. A circular spinner is one element. Both are CSS only and need no JavaScript plugin.

Linear

A bar with a value is determinate. Omit it for an indeterminate bar. The fill is primary on a secondary-container track.

Determinate
<progress class="progress" value="70" max="100"></progress>

A div still works. Set the width on .determinate, or set --md-comp-progress-value on the bar.

<div class="progress" role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100">
  <div class="determinate" style="width: 70%"></div>
</div>

<div class="progress" role="progressbar" aria-valuenow="70" aria-valuemin="0" aria-valuemax="100" style="--md-comp-progress-value: 70%"></div>
Indeterminate
<progress class="progress"></progress>

The child class is the alias:

<div class="progress" role="progressbar">
  <div class="indeterminate"></div>
</div>
End stop and wave

Add stop to put a 4dp dot in the indicator colour at the track's end. It shows where the bar ends when the track has too little contrast with the page. Add wavy to draw the indicator as a wave over a thin track, the M3 Expressive look for a longer wait. The bar grows to 14px to hold the wave, and --md-comp-progress-wavelength sets its period. Both classes work on <progress>, a .determinate child and a bare bar. A wavy bar can also be indeterminate.

<progress class="progress stop" value="40" max="100"></progress>
<progress class="progress wavy stop" value="60" max="100"></progress>
<progress class="progress wavy"></progress>

Circular

For an indeterminate wait under about five seconds, prefer the loading indicator. It replaces the indeterminate circular spinner as the default for a short wait. The indeterminate spinner below still works and is not deprecated.

The spinner is one element. The default size is 48px, small is 36px, and big is 64px. It uses the primary token, and prefers-reduced-motion freezes the arc.

<span class="progress circular" role="status" aria-label="Loading"></span>
<span class="progress circular small" role="status" aria-label="Loading"></span>
<span class="progress circular big" role="status" aria-label="Loading"></span>

Add determinate and set --md-comp-progress-value for a known percentage.

<span class="progress circular determinate"
      style="--md-comp-progress-value: 70%"
      role="progressbar" aria-valuenow="70"
      aria-valuemin="0" aria-valuemax="100"
      aria-label="Loading"></span>

wavy draws the indicator as a wave round the ring, the M3 Expressive look for a longer wait. A determinate wavy ring keeps a thin plain track after the wave. A wavy spinner has none.

<span class="progress circular wavy" role="status" aria-label="Loading"></span>
<span class="progress circular wavy determinate"
      style="--md-comp-progress-value: 65%"
      role="progressbar" aria-valuenow="65"
      aria-valuemin="0" aria-valuemax="100"
      aria-label="Uploading"></span>

Meter

A <progress> shows how far a task has gone. A <meter> shows a measurement within a known range, such as storage used or password strength. It needs no class. Every meter gets an 8px bar on a secondary-container track and fills its container's width. Set width on a meter to keep it inline.

Set the native low, high and optimum attributes to choose the fill color. A value in the same region as optimum is primary, one region away is tertiary, and two regions away is error. In the storage example below, less is better, so optimum sits below low.

40 GB

70 GB

95 GB

<label for="storage">Storage used: 70 GB of 100 GB</label>
<meter id="storage" min="0" max="100" low="60" high="85" optimum="0" value="70">70 GB</meter>

Give each meter a visible label that states the value. The color alone does not tell anyone whether the reading is good. Override --md-comp-meter-track, --md-comp-meter-optimum, --md-comp-meter-suboptimum, --md-comp-meter-even-less-good, --md-comp-meter-thickness and --md-comp-meter-shape to change the colors, height and corner radius.

Colors

The indicator follows the theme. Override --md-comp-progress-indicator to use another role.

<span class="progress circular"
      style="--md-comp-progress-indicator: var(--md-sys-color-error)"
      role="status" aria-label="Loading"></span>

No matching pages

  • Source color

    The seed every generated ramp derives from. Pick one and browse the docs — the whole theme follows. Error does not: it is a fixed hue.

    Default source: Mist Iris.

    ExpressiveCSS presets: Lagoon, Harbor, Breeze, Cobalt, Iris.

    Bold

    Soft

    Mist

    Glow