How to Implement Spring Animations with Framer Motion: A Complete Guide

Use the useSpring hook from Framer Motion to transform raw input values into physics-based motion with configurable mass, stiffness, and damping parameters.

To implement spring animations with Framer Motion effectively, the emilkowalski/skills repository provides a comprehensive reference architecture centered on the useSpring hook. This approach replaces static easing curves with simulated physics, creating UI elements that feel natural and responsive to user interactions.

Why Use Spring Animations?

Spring-based animations simulate real-world physics instead of following predetermined curves, giving interfaces an "alive" quality that static transitions cannot match.

Momentum and Interruptibility

Springs retain velocity when animations are interrupted, allowing gestures like drag, hover, or tap to reverse or change direction smoothly. According to the source code in skills/emil-design-eng/SKILL.md, this is the primary advantage over CSS keyframes, which always restart from zero when interrupted.

Decorative Interactions

For mouse-tracking effects and decorative UI elements, springs add subtle bounce and damping that makes motion feel purposeful rather than artificial. The repository emphasizes this pattern for creating premium-feeling interactions without complex manual calculations.

Configurable Physics Parameters

Framer Motion exposes the underlying physics through intuitive configuration options. The emilkowalski/skills repository documents two primary approaches:

  • Apple-style preset: { type: "spring", duration: 0.5, bounce: 0.2 } for standard UI springs
  • Full physics model: { type: "spring", mass: 1, stiffness: 100, damping: 10 } for fine-tuned control

The useSpring Hook Architecture

The recommended architectural pattern from skills/emil-design-eng/SKILL.md follows four distinct steps:

  1. Read raw input from events or state (e.g., mouseX position)
  2. Create a spring value using useSpring(rawValue, config)
  3. Apply the spring to motion props or inline styles (style={{ rotate: springValue }})
  4. Customize physics through stiffness, damping, mass, or bounce parameters

This declarative pattern keeps components focused on UI logic while Framer Motion handles the physics simulation internally.

Implementation Examples

Basic Mouse Rotation with useSpring

This example from the repository demonstrates tracking mouse position with spring-physics interpolation:

import { useSpring, motion } from 'framer-motion';
import { useState } from 'react';

function RotatingBox() {
  const [mouseX, setMouseX] = useState(0);

  // Spring-interpolated value with physics configuration
  const springRotation = useSpring(mouseX * 0.1, {
    stiffness: 100,
    damping: 10,
  });

  return (
    <div
      onMouseMove={e => setMouseX(e.clientX)}
      style={{ width: 200, height: 200, background: '#61dafb' }}
    >
      <motion.div
        style={{
          width: '100%',
          height: '100%',
          rotate: springRotation,
          originX: 0.5,
          originY: 0.5,
        }}
      />
    </div>
  );
}

The springRotation value smoothly follows the mouse coordinates with configurable resistance, defined in skills/emil-design-eng/SKILL.md.

Drag-to-Dismiss Interactions

For gesture-based dismissal patterns, combine useSpring with Framer Motion's drag handlers:

import { motion, useSpring } from 'framer-motion';
import { useState } from 'react';

function DismissableCard() {
  const [dragX, setDragX] = useState(0);
  const springX = useSpring(dragX, {
    type: 'spring',
    mass: 0.8,
    stiffness: 120,
    damping: 12,
  });

  return (
    <motion.div
      drag="x"
      dragConstraints={{ left: 0, right: 0 }}
      onDrag={(e, info) => setDragX(info.point.x)}
      style={{ x: springX, width: 300, height: 150, background: '#fff' }}
    />
  );
}

This pattern ensures the card maintains momentum when released, creating a tactile feel that static animations cannot replicate.

Reusable Spring Hook Utility

For consistent physics across components, extract the pattern into a custom hook:

import { useSpring } from 'framer-motion';
import { useEffect, useState } from 'react';

export function useResponsiveSpring(
  value: number, 
  config = { stiffness: 100, damping: 10 }
) {
  const spring = useSpring(value, config);
  const [current, setCurrent] = useState(value);

  useEffect(() => {
    setCurrent(value);
  }, [value]);

  return spring;
}

Usage: const ySpring = useResponsiveSpring(scrollY, { stiffness: 80, damping: 15 });

Configuration Presets and Physics Parameters

The emilkowalski/skills repository recommends specific configurations for different interaction types:

  • Standard UI springs: Use the Apple-style preset with duration and bounce for predictable, polished motion
  • Physics-heavy interactions: Specify mass, stiffness, and damping directly when you need precise control over weight and resistance

As documented in skills/review-animations/STANDARDS.md, the design rule "interpolate with useSpring for mouse interactions" should guide architectural decisions when implementing tracking effects.

Summary

  • Use useSpring from Framer Motion to implement physics-based animations that feel natural and responsive
  • Reference skills/emil-design-eng/SKILL.md for the core guide on spring implementation and configuration presets
  • Leverage interruptibility by using springs for gestures, as springs maintain velocity when interrupted unlike CSS keyframes
  • Choose between presets: Use the Apple-style { type: "spring", duration: 0.5, bounce: 0.2 } for standard UI, or full physics parameters for custom feel
  • Apply the 4-step pattern: Read input → Create spring → Apply to styles → Customize physics

Frequently Asked Questions

What is the difference between useSpring and animate props in Framer Motion?

The useSpring hook creates a reactive motion value that continuously interpolates toward its target using physics simulation, while the animate prop applies discrete animations to properties. Use useSpring when you need continuous tracking of changing values (like mouse position), and animate for state-based transitions between discrete values.

When should I use springs instead of CSS transitions?

Use springs when you need interruptibility and momentum preservation during user interactions. According to the repository's analysis in skills/emil-design-eng/SKILL.md, CSS transitions and keyframes always restart from zero when interrupted, creating jarring experiences during drag or hover gestures. Springs maintain velocity and direction changes smoothly.

How do I choose the right stiffness and damping values?

Stiffness controls the spring's tension (higher values = faster movement), while damping controls friction (higher values = quicker settling). The repository recommends starting with { stiffness: 100, damping: 10 } and adjusting: increase stiffness for snappier response, increase damping to reduce oscillation. For most UI elements, the Apple-style preset { type: "spring", duration: 0.5, bounce: 0.2 } provides balanced defaults.

Can useSpring handle interruptible animations during user gestures?

Yes, this is the primary advantage of the useSpring hook. As implemented in the emilkowalski/skills source code, springs retain velocity when interrupted, allowing drag gestures to reverse direction or change target values smoothly without resetting to zero. This creates the "alive" feel characteristic of high-quality interactive interfaces.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →