Skip to content

Motion

Motion in M3 Expressive is physics: springs with a damping ratio and a stiffness, in two schemes. Spatial springs move things and may overshoot; effects springs fade and recolor, and never do.

The springs

Each scheme has six springs: fast, default and slow, for spatial and for effects changes. Use spatial springs for position, size, scale, rotation, corner radius and shape morph; effects springs for color, opacity and elevation. Fast suits small components, default most transitions, slow large or full-screen ones. The expressive scheme is the default; createTheme({ motionScheme: 'standard' }) switches.

Spring Expressive ζ / k Standard ζ / k Expressive settle (ms) Standard settle (ms)
fast-spatial 0.6 / 800 0.9 / 1400 420 229
default-spatial 0.8 / 380 0.9 / 700 475 324
slow-spatial 0.8 / 200 0.9 / 300 655 496
fast-effects 1 / 3800 1 / 3800 149 149
default-effects 1 / 1600 1 / 1600 230 230
slow-effects 1 / 800 1 / 800 326 326

ζ is the damping ratio (1 never overshoots) and k the stiffness, with a mass of 1. The settle time is Compose's own estimate for the spring, the duration of its CSS curve.

Curves

Progress over each spring's settle time; the dashed line is the end value. Expressive spatial springs overshoot and come back; effects springs approach it from below.

  • expressive · fast-spatial
  • expressive · default-spatial
  • expressive · slow-spatial
  • expressive · fast-effects
  • expressive · default-effects
  • expressive · slow-effects
  • standard · fast-spatial
  • standard · default-spatial
  • standard · slow-spatial
  • standard · fast-effects
  • standard · default-effects
  • standard · slow-effects

Try them

Each dot crosses its track with one spring's CSS curve and duration. Press Play again to go back.

  • expressive · fast-spatial
  • expressive · default-spatial
  • expressive · slow-spatial
  • standard · fast-spatial
  • standard · default-spatial
  • standard · slow-spatial

In CSS

Each spring is a linear() easing and a duration: Compose's spring simulation sampled every millisecond and reduced to at most 40 stops. The unprefixed tokens follow the active scheme; the -standard- and -expressive- ones are fixed. A cubic-bezier fallback from m3.material.io is there too (-bezier, -bezier-duration).

.panel {
  transition:
    translate var(--m3e-sys-motion-spring-default-spatial-duration)
      var(--m3e-sys-motion-spring-default-spatial-easing),
    opacity var(--m3e-sys-motion-spring-default-effects-duration)
      var(--m3e-sys-motion-spring-default-effects-easing);
}

A CSS curve cannot carry velocity into an interruption: it restarts. Gestures, drags and fast toggles use the JavaScript springs in @kyralabs/m3e-motion instead, as the components do. Under prefers-reduced-motion: reduce the spatial tokens snap (duration 0) and the default and slow effects use the fast effects curve.

Sources

  • Spring parameters: StandardMotionTokens.kt L20–31 and ExpressiveMotionTokens.kt L22–33 at the pinned commit, generated (FOUNDATIONS_SPEC §4).
  • Curves: a port of Compose's SpringSimulation; durations from FloatSpringSpec.getDurationNanos. Bezier fallback: m3.material.io, Motion overview › Specs.