/react-spring

🙌 Helping react-motion and animated to become best friends

Primary LanguageJavaScriptMIT LicenseMIT

Patreon donate button Backers on Open Collective Sponsors on Open Collective Build Status npm version react version Join the community on Spectrum code style: prettier

npm install react-spring

Table of Contents

What is it?

A set of spring-physics based primitives (as in building blocks) that should cover most of your UI related animation needs once plain CSS can't cope any longer. Forget easings, durations, timeouts and so on as you fluidly move data from one state to another. This isn't meant to solve each and every problem but rather to give you tools flexible enough to confidently cast ideas into moving interfaces.

Why do we need yet another?

react-spring is a cooked down fork of Christopher Chedeau's animated (which is used in react-native by default). It is trying to bridge it with Cheng Lou's react-motion. Although both are similarily spring-physics based they are still polar opposites.

Declarative Primitives Interpolations Performance
React-motion  
Animated      
React-spring  

react-spring builds upon animated's foundation, making it leaner and more flexible. It inherits react-motions declarative api and goes to great lengths to simplify it. It has lots of useful primitives, can interpolate mostly everything and last but not least, can animate by committing directly to the dom instead of re-rendering a component frame-by-frame.

For a more detailed explanation read Why React needed yet another animation library.

What others say

Used by

And many others ...

API Reference and examples

You'll find a full docs, live playgrounds, prop descriptions and so forth here:

Basic overview

Springs (Demo)

A Spring will move data from one state to another. It remembers the current state, value changes are always fluid.

import { Spring } from 'react-spring'

<Spring from={{ opacity: 0 }} to={{ opacity: 1 }}>
  {styles => <div style={styles}>i will fade in</div>}
</Spring>

Mount/unmount Transitions (Demo)

Transition watches elements as they mount and unmount, it helps you to animate these changes.

import { Transition } from 'react-spring'

<Transition
  keys={items.map(item => item.key)}
  from={{ opacity: 0, height: 0 }}
  enter={{ opacity: 1, height: 20 }}
  leave={{ opacity: 0, height: 0, pointerEvents: 'none' }}>
  {items.map(item => styles => <li style={styles}>{item.text}</li>)}
</Transition>

2-state and 1-state Reveals (Demo)

Given a single child instead of a list you can toggle between two components.

import { Transition } from 'react-spring'

<Transition from={{ opacity: 0 }} enter={{ opacity: 1 }} leave={{ opacity: 0 }}>
  {toggle
    ? styles => <div style={styles}>Component A</div>
    : styles => <div style={styles}>Component B</div>
  }
</Transition>

If you need to toggle a single child, that is also possible.

import { Transition } from 'react-spring'

<Transition from={{ opacity: 0 }} enter={{ opacity: 1 }} leave={{ opacity: 0 }}>
  {visible && (styles => <div style={styles}>Single Component</div>)}
</Transition>

Trails and staggered animations (Demo)

Trail animates the first child of a list of elements, the rest follow the spring of their previous sibling.

import { Trail } from 'react-spring'

<Trail from={{ opacity: 0 }} to={{ opacity: 1 }} keys={items.map(item => item.key)}>
  {items.map(item => styles => <div style={styles}>{item.text}</div>)}
</Trail>

Keyframes (Demo)

Keyframes allow you to chain, compose and orchestrate animations by creating predefined slots. The resulting primitive behaves like the primitive it stems from, it can receive all generic properties like native or from, etc. You make it animate by passing the state props, which receives the named slot.

import { Keyframes, config } from 'react-spring'

// You can create keyframes for springs, trails and transitions
const Container = Keyframes.Spring({
  // Single props
  show: { to: { opacity: 1 } },
  // Chained animations (arrays)
  showAndHide: [ { to: { opacity: 1 } }, { to: { opacity: 0 } }],
  // Functions with side-effects
  wiggle: async call => {
    await call({ to: { x: 100 }, config: config.wobbly })
    await delay(1000)
    await call({ to: { x: 0 }, config: config.gentle })
  }
})

<Container state="show">
  {styles => <div style={styles}>Hello</div>}
</Container>

Parallax and page transitions (Demo)

Parallax allows you to declaratively create page/scroll-based animations.

import { Parallax, ParallaxLayer } from 'react-spring'

<Parallax pages={2}>
  <ParallaxLayer offset={0} speed={0.2}>
    first Page
  </ParallaxLayer>
  <ParallaxLayer offset={1} speed={0.5}>
    second Page
  </ParallaxLayer>
</Parallax>

Time/duration-based implementations and addons (Demo)

You'll find varying implementations under /dist/addons. For now there's a time-based animation as well common easings, and IOS'es harmonic oscillator spring. All primitives understand the impl property which you can use to switch implementations.

import { TimingAnimation, Easing } from 'react-spring/dist/addons'

<Spring impl={TimingAnimation} config={{ duration: 1000, easing: Easing.linear }} >

Interpolation

We don't handle just numbers, you can interpolate almost everything:

  • colors (names, rgb, rgba, hsl, hsla)
  • absolute lenghts (cm, mm, in, px, pt, pc)
  • relative lengths (em, ex, ch, rem, vw, vh, vmin, vmax, %)
  • angles (deg, rad, grad, turn)
  • flex and grid units (fr, etc)
  • all HTML attributes
  • SVG paths (as long as the number of points matches, otherwise use custom interpolation)
  • arrays
  • string patterns (transform, border, boxShadow, etc)
  • auto is valid
  • non-animatable string values (visibility, pointerEvents, etc)
  • scrollTop/scrollLeft (native only, since these aren't actual dom properties)
<Spring
  to={{
    width: 'auto',
    padding: 20,
    width: '80%',
    background: 'linear-gradient(to right, #009fff, #ec2f4b)',
    transform: 'perspective(600px) translate3d(0px,0,0) scale(1) rotateX(0deg)',
    boxShadow: '0px 10px 20px 0px rgba(0,0,0,0.4)',
    borderBottom: '10px solid #2D3747',
    shape: 'M20,20 L20,380 L380,380 L380,20 L20,20 Z',
    textShadow: '0px 5px 15px rgba(255,255,255,0.5)' }}>

Native rendering

img img
Most libs animate by having React recalculate the component-tree on every frame. Here it attempts to animate a component consisting of ~300 sub-components, plowing through the frame budget and causing jank. React-spring with the native property renders the component only once, from then on the animation will be applied directly to the dom in a requestAnimationFrame-loop, similar to how gsap and d3 do it.
import { Spring, animated } from 'react-spring'

<Spring native from={{ opacity: 0 }} to={{ opacity: 1 }}>
  {styles => <animated.div style={styles}>i will fade in</animated.div>}
</Spring>

Native rendering comes with a few caveats you should know about before using it, more about that here. Try going native in all situations where you can, the benefits are worth it!

Funding

If you like this project, consider helping out, all contributions are welcome as well as donations to opencollective or Patreon. You can make one off donations in crypto to 36fuguTPxGCNnYZSRdgdh6Ea94brCAjMbH (BTC).

Contributors

This project exists thanks to all the people who contribute.

Backers

Thank you to all our backers! 🙏

Gold sponsors

Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website.