material-loading-indicator

MD3 Expressive loading indicator — spins while morphing through 7 shapes (~4.7s cycle). default sits on a surface; contained adds a primary-container disk for placement over content.

Default — sizes

Bare active indicator on a surface. Color tracks primary. Spec range 24–240dp; default 48dp.

24
48 (default)
96
160

Contained — sizes

Adds a circular primary-container disk; indicator fills with on-primary-container. Use over content (cards, images, lists), or for pull-to-refresh.

24
48 (default)
96
160

Over content

Centered above a busy surface. The contained variant carries enough contrast to remain legible without dimming the underlying content.

contained over content

default on a surface

In a button — async action

Drop the indicator alongside a button label while an action is pending. Toggle paused to freeze for snapshot tests or visual debugging.

Saving… Toggle paused running

Reduced motion

When the OS reports prefers-reduced-motion: reduce, the morph is held on shape #4 (squircle) and the spin slows to ~12s per turn. Toggle Rendering ▸ Emulate prefers-reduced-motion in DevTools to preview.

Same component — behavior is purely OS/preference-driven.

Sample usage
<!-- Default — bare active indicator on a surface -->
<material-loading-indicator label="Loading news article"></material-loading-indicator>

<!-- Contained — disk for placement over content / pull-to-refresh -->
<material-loading-indicator variant="contained" size="56"
                            label="Refreshing feed"></material-loading-indicator>

<!-- Inside a button while an action is pending -->
<material-button variant="filled" disabled>
  <material-loading-indicator size="20" variant="contained" label="Saving"></material-loading-indicator>
  Saving…
</material-button>

<!-- Pause both spin + morph (e.g., for visual regression tests) -->
<material-loading-indicator paused></material-loading-indicator>