Components

Motion & Behavior

Purposeful animation that communicates, not decorates. Every transition, every easing curve, every duration serves a function.

Principles

Motion Philosophy

Apple's approach to motion is grounded in three core principles. Animation should never exist just to impress — it should communicate, orient, and delight in service of the user's goals.

Purposeful

Motion communicates state changes, confirms actions, and guides attention. Never decorative. Every animation has a reason to exist.

Physical

Animations follow physical laws — spring physics, inertia, momentum. Objects feel like they have weight and respond naturally to interaction.

Respectful

Always honor prefers-reduced-motion. Users with vestibular disorders or motion sensitivity must always be considered.

prefers-reduced-motion Respect. Always.
Reference

Easing Functions

Easing curves define how an animation accelerates and decelerates. The right curve makes motion feel natural; the wrong one feels mechanical or jarring.

Hover each row to see the animation play

linear
ease
standard
spring
decelerate
Name Curve Best For
linear constant speed Opacity fades, color transitions
ease slow → fast → slow General purpose hover states
standard HIG cubic-bezier(0.2, 0, 0, 1) Most UI transitions, element movement
spring cubic-bezier(0.34, 1.56, 0.64, 1) Buttons, cards, modals appearing
decelerate cubic-bezier(0, 0, 0.2, 1) Elements entering the screen
Tokens

Duration Reference

Consistency in timing makes an interface feel cohesive. Use the right duration token for every interaction type.

Token Value Visual Use Case
--duration-instant 100ms
Hover states, color changes
--duration-fast 200ms
Small UI feedback, button press
--duration-normal 300ms
Most UI transitions
--duration-slow 500ms
Page/screen transitions
--duration-slower 700ms
Complex entrance animations
Interactive Demo

Transition Types

Five core transition patterns cover virtually every UI motion need. Click each "Play" button to see the animation in action.

Fade

opacity 0 → 1
200ms ease

Aa

Scale

scale 0.95 → 1 + fade
250ms spring

Aa

Slide Up

translateY(12px) → 0 + fade
300ms decelerate

Aa

Slide In

translateX(-20px) → 0 + fade
300ms decelerate

Aa

Spring Scale

scale 0.8 → 1.05 → 1
spring easing

Aa
Real Examples

Functional Motion Examples

These real-world animation patterns solve specific UX problems. Each exists to communicate something — not to impress.

Loading → Content

Skeleton screens reduce perceived load time and prevent layout shift.

A
Alex Johnson
2 minutes ago

The new motion system looks incredibly polished. Great work on the spring easing!

Success Confirmation

A spring-animated checkmark confirms the action completed successfully.

Saved successfully

Form Validation

A brief shake communicates an error without being disruptive or alarming.

Expand / Collapse

Directional arrow rotation signals the state before the content animates open.

Liquid Glass is Apple's adaptive material that captures and refracts light, creating a sense of depth and hierarchy in interfaces.
Blur is appropriate for persistent UI elements (navigation bars, sidebars) that sit above content layers and need to visually separate from the content beneath.
Most UI transitions should be 200–300ms. Anything longer feels sluggish; anything faster may be imperceptible. Page-level transitions can go up to 500ms.
Accessibility

Reduced Motion

The prefers-reduced-motion media query is non-negotiable. Users with vestibular disorders can experience nausea or disorientation from motion. Always provide a static alternative.

With Motion

Animation plays normally for users who haven't opted out

Reduced Motion

Static fallback — shape/color conveys state without motion

CSS
/* ✅ Always wrap animations in a media query */
.animated-element {
  transition: transform 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@media (prefers-reduced-motion: reduce) {
  .animated-element {
    /* Remove animation, keep functional state */
    transition: none;
  }

  /* Or use instantaneous transitions */
  * {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
Implementation

CSS Implementation

Complete utility classes and CSS custom properties for implementing the motion system in any project.

design-tokens-motion.css
:root {
  /* Duration Tokens */
  --duration-instant: 100ms;
  --duration-fast:    200ms;
  --duration-normal:  300ms;
  --duration-slow:    500ms;
  --duration-slower:  700ms;

  /* Easing Tokens */
  --easing-linear:     linear;
  --easing-standard:   cubic-bezier(0.2, 0, 0, 1);
  --easing-decelerate: cubic-bezier(0, 0, 0.2, 1);
  --easing-accelerate: cubic-bezier(0.3, 0, 1, 1);
  --easing-spring:     cubic-bezier(0.34, 1.56, 0.64, 1);
}

/* Utility: Fade in */
@keyframes fadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* Utility: Scale in */
@keyframes scaleIn {
  from { opacity: 0; transform: scale(0.95); }
  to   { opacity: 1; transform: scale(1); }
}

/* Utility: Slide up */
@keyframes slideUp {
  from { opacity: 0; transform: translateY(12px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Utility: Slide in from left */
@keyframes slideInLeft {
  from { opacity: 0; transform: translateX(-20px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Animation utility classes */
.animate-fade-in    { animation: fadeIn var(--duration-fast) var(--easing-standard) both; }
.animate-scale-in   { animation: scaleIn var(--duration-normal) var(--easing-spring) both; }
.animate-slide-up   { animation: slideUp var(--duration-normal) var(--easing-decelerate) both; }
.animate-slide-left { animation: slideInLeft var(--duration-normal) var(--easing-decelerate) both; }

/* Stagger children with delay */
.stagger > *:nth-child(1) { animation-delay: 0ms; }
.stagger > *:nth-child(2) { animation-delay: 50ms; }
.stagger > *:nth-child(3) { animation-delay: 100ms; }
.stagger > *:nth-child(4) { animation-delay: 150ms; }

/* Respect reduced motion */
@media (prefers-reduced-motion: reduce) {
  * {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}