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