Skip to main content

Installation

Install React Spring via npm or yarn:
npm install @react-spring/web

Basic usage

React Spring uses spring-physics to create natural-looking animations. The core hook is useSpring, which returns animated values you can apply to elements.
import { useSpring, animated } from '@react-spring/web'
import { useState } from 'react'

function SpringAnimation() {
  const [isVisible, setIsVisible] = useState(true)
  
  const springProps = useSpring({
    scale: isVisible ? 1 : 0,
    opacity: isVisible ? 1 : 0,
    config: { tension: 300, friction: 10 }
  })

  return (
    <>
      <animated.div
        style={{
          ...springProps,
          width: 100,
          height: 100,
          background: '#10B981',
          borderRadius: 8
        }}
      />
      <button onClick={() => setIsVisible(!isVisible)}>
        Toggle
      </button>
    </>
  )
}

Configuration options

React Spring provides intuitive physics-based configuration:
Controls the spring’s strength. Higher values create faster, snappier animations.
config: { tension: 300 } // Snappy
config: { tension: 100 } // Gentle

Key features

Spring physics

Natural motion based on spring physics rather than duration-based easing curves.

Interpolation

Smoothly interpolate between any values including colors, transforms, and custom properties.

Performance

Runs animations off the main thread for smooth 60fps performance.

Declarative

Define what you want animated, not how it should animate.

Multiple values with useSpring

Animate multiple properties simultaneously:
const props = useSpring({
  from: { opacity: 0, transform: 'translateY(-40px)' },
  to: { opacity: 1, transform: 'translateY(0px)' },
  config: { tension: 300, friction: 20 }
})

return <animated.div style={props}>Content</animated.div>

Chaining animations with useChain

Orchestrate multiple animations in sequence:
import { useSpring, useChain, useSpringRef } from '@react-spring/web'

function ChainedAnimation() {
  const springRef = useSpringRef()
  const spring = useSpring({
    ref: springRef,
    from: { scale: 0 },
    to: { scale: 1 }
  })
  
  const fadeRef = useSpringRef()
  const fade = useSpring({
    ref: fadeRef,
    from: { opacity: 0 },
    to: { opacity: 1 }
  })
  
  useChain([springRef, fadeRef], [0, 0.5])
  
  return <animated.div style={{ ...spring, ...fade }} />
}

Trail animations

Animate a list of items with a stagger effect:
import { useTrail, animated } from '@react-spring/web'

function Trail({ items }) {
  const trail = useTrail(items.length, {
    from: { opacity: 0, x: -20 },
    to: { opacity: 1, x: 0 }
  })
  
  return trail.map((props, index) => (
    <animated.div key={index} style={props}>
      {items[index]}
    </animated.div>
  ))
}

When to use it

Choose React Spring when you want animations that feel natural and organic, mimicking real-world physics instead of artificial easing curves.
Perfect when you want great-looking animations without tweaking duration and easing values. Spring physics automatically creates smooth motion.
Ideal for animations that change direction mid-flight or respond to rapidly changing data without jarring transitions.
React Spring runs animations off the main thread, making it excellent for performance-sensitive applications.

Comparison with Framer Motion

Both libraries are excellent choices, but they have different philosophies:
Strengths:
  • Spring-physics based (more natural motion)
  • Smaller bundle size
  • Automatic interruption handling
  • Runs off main thread
Best for:
  • Data visualizations
  • Smooth, natural transitions
  • Performance-critical applications

Example from the playground

Here’s the comparison demo from the Animation Playground:
import { useSpring, animated } from '@react-spring/web'
import { useState } from 'react'

function ComparisonDemo() {
  const [isVisible, setIsVisible] = useState(true)

  const springStyle = useSpring({
    scale: isVisible ? 1 : 0,
    config: { tension: 300, friction: 20 }
  })

  return (
    <div>
      <animated.div
        style={{
          ...springStyle,
          width: '8rem',
          height: '8rem',
          backgroundColor: '#10B981',
          borderRadius: '0.5rem'
        }}
      />
      <button onClick={() => setIsVisible(!isVisible)}>
        Toggle Animation
      </button>
    </div>
  )
}

Learn more

Animation examples

See React Spring in action

Official docs

Visit the React Spring documentation

Build docs developers (and LLMs) love