← All motion systems
Motion System

Google Material Design 3

Expressive, purposeful, and fully specified — motion that communicates spatial relationships and component state at every scale.

get_motion("google-material")
Browse all

Motion System: Google Material Design 3

Category: Design System Expressive, purposeful, and fully specified — motion that communicates spatial relationships and component state at every scale.

Motion Philosophy

Material Design 3 motion is grounded in a single principle: motion should be meaningful. Every transition should help users understand what happened, where they came from, and where they are going. The M3 motion system does this by treating the UI as a physical space — elements that share a relationship move together, elements entering from outside the current context slide in from the appropriate edge, and containers that expand into new content do so in a way that preserves spatial memory. Motion is never decorative; it is always communicative.

M3 introduces a distinction between "expressive" and "functional" motion. Expressive motion applies to components that carry personal or brand significance — FABs, navigation bars, large interactive surfaces — and is allowed to be springy, slightly bouncy, and perceptually longer. Functional motion applies to utility components — chips, checkboxes, progress indicators — and uses tighter, more linear transitions. This distinction lets M3 be both systematic (every component has a specified motion) and human (key moments in the interface feel genuinely alive). Springs are used deliberately for expressive components; the spring values chosen have a gentle overshoot that reads as organic without feeling unpolished.

The M3 specification is exhaustive. Duration tokens span from 50ms (instant micro-interactions) to 700ms (complex hero transitions). Four named easing curves cover every case: Emphasized for most enter/move transitions, Emphasized Decelerate for entering elements, Emphasized Accelerate for exiting elements, and Standard for small utility transitions. These map to specific cubic-bezier values that are non-negotiable within the system — the goal is that any component built by any team, at any Google product, produces the same motion timing.

Duration Scale

TokenValueUse
instant0msState changes with no perceptible visual element (internal data, hidden toggles)
short150msIcon micro-animations, checkmark fills, very small state changes
short2100msSmall component state changes: chip selection, radio button
short3150msTooltip appearance, badge update, small icon swap
short4200msSmall components entering/exiting: snackbar, small dialog
medium1250msStandard component transitions: nav drawer closing, bottom sheet small
medium2300msNavigation transitions, tab switches, default modal enter
medium3350msShared axis transitions, page-level panel transitions
medium4400msContainer transforms, large modal dialogs
long1450msBottom sheet full expand, large drawer
long2500msComplex container transforms, FAB morphing to dialog
long3550msHero transitions, screen-level shared element transitions
long4600msComplex screen transitions with multiple coordinated elements
extra-long1700msOnboarding sequences, full-page expressive entrances

Easing

TokenCurveUse
emphasizedcubic-bezier(0.2, 0, 0, 1)Elements moving within the screen — the default for most transitions
emphasized-deceleratecubic-bezier(0.05, 0.7, 0.1, 1)Elements entering the screen from outside — decelerates sharply
emphasized-acceleratecubic-bezier(0.3, 0, 0.8, 0.15)Elements exiting the screen — accelerates quickly away
standardcubic-bezier(0.2, 0, 0, 1)Utility components, functional transitions (same curve as emphasized, shorter durations)
standard-deceleratecubic-bezier(0, 0, 0, 1)Small components entering
standard-acceleratecubic-bezier(0.3, 0, 1, 1)Small components exiting
linearcubic-bezier(0, 0, 1, 1)Progress indicators, continuous animations

The emphasized curve is the workhorse of M3. Its shape front-loads acceleration and then decelerates gently, giving motion a sense of physical presence without overshoot.

Spring Configs (Framer Motion / react-spring)

Used for expressive components only (FAB, navigation bar active indicator, extended FAB).

  • Default (expressive): stiffness: 380, damping: 30, mass: 1
  • Snappy (nav indicator): stiffness: 500, damping: 35, mass: 0.8
  • Bouncy (FAB press): stiffness: 300, damping: 20, mass: 1 — intentional slight overshoot, use only for FAB and similar hero actions
  • Gentle (bottom sheet): stiffness: 200, damping: 28, mass: 1.2

Springs are not used for functional components (chips, checkboxes, text fields, dialogs). Those use duration + easing only.

Stagger Patterns

  • List items: 40ms between each item, emphasized-decelerate
  • Cards in grid: 50ms between each card, triggered on scroll into view
  • Navigation rail items: 30ms between each item on mount
  • Chips in a chip group: 25ms between each chip when group appears
  • Children in container transform: stagger begins 50ms after container starts expanding

Enter / Exit Patterns

Fade Through (switching between unrelated destinations — tab content swap)

outgoing: opacity 1→0, scale 1→0.92, duration: short4 (200ms), ease: emphasized-accelerate
incoming: opacity 0→1, scale 0.92→1, duration: medium2 (300ms), ease: emphasized-decelerate
incoming begins after outgoing is 50% complete

Shared Axis — Horizontal (forward/back navigation between related screens)

forward enter: translateX 30%→0, opacity 0→1, duration: medium3 (350ms), ease: emphasized
forward exit: translateX 0→-30%, opacity 1→0, duration: medium3 (350ms), ease: emphasized
backward reverses directions

Shared Axis — Vertical (drill-down into list item, expanding section)

enter: translateY 30%→0, opacity 0→1, duration: medium3 (350ms), ease: emphasized-decelerate
exit: translateY 0→-30%, opacity 1→0, duration: medium2 (300ms), ease: emphasized-accelerate

Container Transform (element expands into full surface — card to detail, FAB to dialog)

container: bounds animate from source element rect to destination rect,
           duration: long2 (500ms), ease: emphasized
content inside: opacity 0→1, duration: short4 (200ms) starting at 300ms into transition
closing reverses: duration: medium4 (400ms), ease: emphasized

Scale Pop (dialogs, menus, popovers)

enter: opacity 0→1, scale 0.8→1, duration: medium2 (300ms), ease: emphasized-decelerate
exit: opacity 1→0, scale 1→0.8, duration: short4 (200ms), ease: emphasized-accelerate

Slide (bottom sheets, navigation drawers, side sheets)

bottom sheet enter: translateY 100%→0, duration: long1 (450ms), ease: emphasized-decelerate
bottom sheet exit: translateY 0→100%, duration: medium4 (400ms), ease: emphasized-accelerate
nav drawer enter: translateX -100%→0, duration: medium4 (400ms), ease: emphasized-decelerate
nav drawer exit: translateX 0→-100%, duration: medium3 (350ms), ease: emphasized-accelerate

Interaction States

  • Hover: State layer (tonal overlay) fades in at 8% opacity over short2 (100ms), standard easing. Elevation increases on cards (shadow deepens) over short3 (150ms). No scale transform.
  • Press/Active: State layer increases to 12% opacity immediately (0ms) on press. For expressive components (FAB, buttons): scale(0.95) using Bouncy spring config. Ripple effect originates from touch point, expands to fill container over medium2 (300ms), linear easing.
  • Focus: Focus ring (3dp, color: secondary) appears over short2 (100ms), standard-decelerate. State layer adds 12% opacity. In M3, focus indicators are never instantaneous — their appearance is a legible signal, not a flash.
  • Drag: Dragged element gains elevation (z-index + shadow increase) over short3 (150ms). Scales to 1.05 using Default spring. Drop target highlights its container background with a tonal fill over short3 (150ms).
  • Loading: Circular progress indicator uses a custom CSS animation: arc length and rotation combine over 1333ms cycle, linear. Linear progress indicator: indeterminate uses two bars at different speeds animating a 200% wide track over 2000ms, standard easing. Skeleton loaders use a shimmer gradient over 1500ms, linear, looping.
  • Selection: Checkbox: checkmark draws via stroke-dashoffset over short3 (150ms), emphasized. Radio: inner circle scales 0→1 over short3 (150ms), emphasized-decelerate. Switch thumb: translateX with snappy spring, track color transitions over short4 (200ms).

Rules

  • Use the correct easing for directionality: entering elements always use a decelerate curve, exiting elements always use an accelerate curve, elements moving within the screen use the standard emphasized curve. Never swap these.
  • Container Transform requires the source element's bounds to be measured before the transition begins. Do not start the animation until the layout is stable and the destination surface is mounted off-screen.
  • Expressive springs (Bouncy config) are reserved for the FAB, extended FAB, and branded hero elements. Dialogs, sheets, and navigation components must use duration-based easing regardless of how interactive they feel.
  • Respect prefers-reduced-motion: replace all transforms with opacity-only transitions, collapse durations to 0ms for purely decorative animations, preserve functional transitions (dialog appearing, bottom sheet opening) at a reduced opacity-only form with short4 (200ms) maximum duration.

Use this in your agent

The DesignMD MCP server returns this full motion system in one call. Combine it with design tokens using get_full_system.

get_full_system("google-material")
Set up MCP →