# How to Configure Spring Animations Using Apple's Approach: Damping, Response, and Interruptibility

> Learn to configure spring animations with Apple's damping ratio and response parameters. Create interruptible springs that preserve velocity for smoother gesture reversals.

- Repository: [Emil Kowalski/skills](https://github.com/emilkowalski/skills)
- Tags: how-to-guide
- Published: 2026-08-06

---

**Apple's motion design replaces the traditional physics triplet (mass, stiffness, damping) with designer-friendly **damping ratio** and **response** parameters, creating interruptible springs that preserve velocity during gesture reversals.**

To configure spring animations using Apple's approach in web projects, reference the `emilkowalski/skills` repository, which documents how to translate Apple's iOS spring physics into web-friendly APIs like Motion and Framer Motion. This methodology treats animation as a physical conversation where UI elements retain momentum and can be re-targeted mid-flight without jarring interruptions.

## Why Apple Replaced the Physics Triplet

According to [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md), Apple deliberately moved away from the classic physics triplet of mass, stiffness, and damping. Instead, they optimize for two intuitive parameters:

- **Damping ratio** – Controls how much the spring oscillates (1.0 = critically damped, no bounce; 0.8 = slight overshoot for momentum-driven gestures)
- **Response** – Defines how quickly the spring settles (typically 0.3–0.4 seconds for standard UI)

This shift makes springs more predictable for designers while maintaining physical accuracy. The repository notes this is **not** equivalent to CSS animation duration—it is the characteristic time scale of the physical system.

## Default Configurations for Different Interactions

The [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md) file provides specific defaults based on interaction type:

| Interaction | Damping | Response | Bounce |
|---|---|---|---|
| Move / Reposition | 1.0 | 0.4s | 0 |
| Momentum gestures (flick, drag-to-dismiss) | 0.8 | 0.4s | 0.2 |

For most UI elements, use a **critically damped** spring (`damping = 1.0`) to avoid overshoot. Reserve under-damped springs (`damping ≈ 0.8`) for momentum-driven interactions where a subtle bounce reinforces the physical metaphor.

## Understanding Interruptibility and Velocity Hand-Off

A core principle documented in [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md) is **interruptibility**: springs must always start from the current *presentation* value (on-screen position) and carry existing velocity when re-targeted. This prevents the "brick wall" effect common in CSS keyframe animations.

When implementing gesture-driven springs, calculate the release velocity and pass it directly to the animation engine:

```javascript
// Calculate velocity from last 5 pointer events
const velocity = (currentPos - lastPos) / (currentTime - lastTime);

// Pass to spring (Motion/Framer Motion accepts px/s)
animate(element, { y: targetY }, {
  type: 'spring',
  bounce: 0.2,
  duration: 0.4,
  velocity  // Preserves gesture momentum
});

```

If your library expects relative velocity rather than absolute, normalize it using `gestureVelocity / (target - current)` as noted in the velocity hand-off section of the Apple design skill.

## Configuring Springs in Web Frameworks

### The Apple-Style Default Configuration

The canonical configuration recorded in [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md) uses Motion's `bounce` and `duration` API to map Apple's damping and response:

```javascript
import { animate } from 'motion';

// Standard UI spring (critically damped)
animate(element, { y: 0 }, {
  type: 'spring',
  bounce: 0,
  duration: 0.4
});

// Momentum-driven interaction (slight bounce)
animate(element, { y: target }, {
  type: 'spring',
  bounce: 0.2,
  duration: 0.5
});

```

### Full Physics Control

For fine-tuned control when the simplified API doesn't suffice, use the full physics form as shown in [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md):

```javascript
animate(element, { x: 150 }, {
  type: 'spring',
  mass: 1,
  stiffness: 100,
  damping: 10  // Under-damped = visible bounce
});

```

### Velocity Hand-Off Implementation

Complete implementation combining gesture tracking with velocity preservation:

```javascript
let moveHistory = []; // Store last 5 pointer events

element.addEventListener('pointermove', (e) => {
  moveHistory.push({ x: e.clientY, t: performance.now() });
  if (moveHistory.length > 5) moveHistory.shift();
});

element.addEventListener('pointerup', (e) => {
  const now = performance.now();
  const oldest = moveHistory[0];
  const velocity = (e.clientY - oldest.x) / (now - oldest.t);
  
  animate(element, { y: 0 }, {
    type: 'spring',
    bounce: 0.2,
    duration: 0.4,
    velocity  // Maintains physical continuity
  });
});

```

## Accessibility and Reduced Motion Support

Per [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md), every spring animation must respect `prefers-reduced-motion`. When this media query is active, replace springs with short opacity cross-fades:

```javascript
import { useReducedMotion } from 'framer-motion';

const shouldReduceMotion = useReducedMotion();

const animationOptions = shouldReduceMotion
  ? { type: 'tween', duration: 0.2, ease: 'linear' }
  : { type: 'spring', bounce: 0.2, duration: 0.4 };

animate(element, { y: target }, animationOptions);

```

## Summary

- **Use damping ratio and response** instead of mass/stiffness/damping for Apple-style springs, as documented in [`skills/apple-design/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/apple-design/SKILL.md).
- **Configure critically damped springs** (`bounce: 0`, `duration: 0.4`) for standard UI moves and **under-damped springs** (`bounce: 0.2`) for momentum gestures.
- **Preserve interruptibility** by starting animations from the current presentation value and carrying velocity through gesture reversals.
- **Hand off release velocity** calculated from pointer history to maintain physical continuity when gestures end.
- **Support reduced motion** by falling back to opacity fades when users prefer minimal animation.

## Frequently Asked Questions

### What is the difference between Apple's spring parameters and traditional physics springs?

Apple's approach uses **damping ratio** and **response** rather than mass, stiffness, and damping. Damping ratio (0.0–1.0) intuitively controls bounciness, while response defines the animation's speed without being a fixed duration. This makes springs easier to tune for designers while maintaining physical accuracy, as implemented in the `emilkowalski/skills` repository's web mapping guidelines.

### How do I convert between Apple's damping ratio and Motion's bounce parameter?

In Motion or Framer Motion, `bounce` maps roughly to `1 - dampingRatio`. A critically damped Apple spring (damping = 1.0) corresponds to `bounce: 0`, while a momentum-driven spring (damping ≈ 0.8) maps to `bounce: 0.2`. The canonical Apple-style configuration in [`skills/improve-animations/AUDIT.md`](https://github.com/emilkowalski/skills/blob/main/skills/improve-animations/AUDIT.md) recommends `{ type: "spring", duration: 0.5, bounce: 0.2 }` for interactive elements.

### When should I use a spring animation versus a standard tween?

Reach for springs for anything the user can touch, according to [`skills/animate/SKILL.md`](https://github.com/emilkowalski/skills/blob/main/skills/animate/SKILL.md). This includes draggable elements, flick-to-dismiss gestures, scroll physics, and any UI that should feel alive and interruptible. Use standard tweens only for decorative transitions that don't respond to user input or when `prefers-reduced-motion` is active.

### How do I prevent springs from jumping when a new gesture starts?

Ensure your animation library starts from the **presentation value** (current on-screen position) rather than the animation target. Pass the current velocity when re-targeting the spring. In Motion, this happens automatically if you call `animate()` on an element already in motion, but verify your velocity calculations use the formula `gestureVelocity / (target - current)` if the library expects relative velocity values.