React Spring 

React 

CSS 

Animations 

Hooks 

JavaScript 

Introduction to Animations in React using React Spring 

Prerequisites 

React 

JavaScript 

CSS 

Published 

31-01-2022 

In this article, we’ll be exploring one of the best React Frameworks for animations, React Spring, and how you can use React Spring to create simple to complex animations that look beautiful.

Prerequisites

While React Spring provides both hook-based and component-based APIs, for the article we’ll exclusively look at the hook-based API for all the animations.

For adding the package to your React project, For npm

npm install react-spring d3-ease

For yarn

yarn add react-spring d3-ease

Here we’re also adding the package d3-ease for using different easing functions to our animations without creating our own. This allows us to create smoothe animations with numerous easing functions at our disposal.

React Spring Hooks

useSpring - A single spring, moves from state A to B.

useSprings - Multiple springs, mainly for list of elements/components, each moving from state A to B.

usesTransition - Multiple springs, one spring follows or ‘trails’ behind the other.

useTrail - For mounting/unmounting animations(for list of components).

useChain - To chain or combine multiple animations together.

For the article, we’ll look at the most basic hook useSpring.

From and To

To use the useSpring hook in our project, we import the hook and animated from the react-spring library. We also import the d3-ease library, though it can be ignored if you want to use other easing functions.

import { useSpring, animated } from ‘react-spring’
import * as easings from ‘d3-ease’

We import animated, as native elements need to know how to handle the animated props you pass to it. Animate does this by extended these native elements so it can be animated out React (for performance reasons).

Next we define our spring. The basic structure for using the useSpring hook is:

const Animate = useSpring({
	from: {
		//Initial CSS Properties here
	},
	to: {
		//Final CSS Properties here
	}
})

Using Functions and States

The useSpring hook can also be declared as a function or use state variables to animate the element.

const Animate = (visible) => useSpring({
	opacity: visible ? '1' : '0'
	// other properties...
})

Config

On its own, the previous useSpring hooks would result in very abrupt animations.

This is due to the hook using default configurations. This can be customized by using the configuration by mentioning in the config section in the hook declaration.

const animation = useSpring({
	from: {
		//your properties here...
	},
	to: {
		// your properties here...
	},
	config: {
		mass: 1,
		tension: 280,
		friction: 120,
		clamp: true
	}
});

There are few pre-defined presets for the config defined in the library

config.default { mass: 1, tension: 170, friction: 26 }

config.gentle { mass: 1, tension: 120, friction: 14 }

config.wobbly { mass: 1, tension: 180, friction: 12 }

config.stiff { mass: 1, tension: 210, friction: 20 }

config.slow { mass: 1, tension: 280, friction: 60 }

config.molasses { mass: 1, tension: 280, friction: 120 }

These presets can be imported from the library

import { useSpring, animated, config } from ‘react-spring’
import * as easings from ‘d3-ease’

const animation = useSpring({
	from: {
		//your properties here...
	},
	to: {
		// your properties here...
	},
	config: {
		...config.gentle
		clamp: true
	}
});

Using React Spring to Animate Typography

In this section, I'll be demonstrating how we can use React Spring to create beautiful Kinetic Typography, like this one.

Animating Background

Firstly, we would have to create the background section and the useSpring hook to animate the background.

/* CSS Style for the div */

.back {
	position: absolute;
	top: 0;
	left: 0;
	height: 100vh;
	width: 100vw;
	display: flex;
	flex-direction: column;
	z-index: -1;
	height: 0vh;
	background: #ffffff;
}
// useSpring hook for div

const BackAnimate = () => useSpring({
	from: {
		height: "0vh"
	}, 
	to: {
		height: "50vh"
	},
	config: {
		easing: easings.easeCubicInOut, 
		duration: 1200
	}
});

This would add the animation to the background <div> which would increase int height to cover 50% of the viewport height. Notice the config settings, we are using easings and duration instead of physics based animations, as this allows us to set the duration, which is not possible with spring based animations.

The hook can be assigned to the <div> in the following manner:

<animated.div className="back" key={1} style={BackAnimate()}></animated.div>

Notice the use of <animated.div> instead of normal div.

animated is used to extend native elements, which allows these elements to bypass React for frame updates and improve performance. It uses the requestAnimationFrame from the windowAPI. The API animates the elements in the background at every repaint, instead of using statevariables to animate elements and re-rendering element again at state change, which native React rendering would perform.

This would give us the required background with the animation as shown below

Animating Text

Next we create the text and its styles along with the useSpring hook to animate the text. Since we have different directions for different texts, we can include direction in the hook

/* CSS Styles for the each of the texts */

.one {
	color: #202020;
	display: inline-block;
	overflow: hidden;
}

.two {
	color: #ffffff;
	display:inline-block;
	overflow: hidden;
}
// useSpring hook for the text

const TextAnimate = (direction) => useSpring({
	from: {
		transform: `translateY(${direction * 30}vh)` 
	}, 
	to: { 
		transform: "translateY(0vh)" 
	}, 
	delay: 1200, 
	config: { 
		easing: easings.easeCubicInOut, 
		duration: 1200 
	} 
});

The styles allow the texts to be outside of their original positions, and also stay hidden. We then change the position of the texts to reveal them by the useSpring hook, which also mentions direction as a parameter. This allows the useSpring hook to be used for both the texts, with just changing the direction for the translation during the animation using template strings. The code combined with the background would result in the below animation

Making the animation complex

The animation could be taken further by creating individual reveal animations for each word by a loop and modifying the useSpring hook in a manner as shown below

// Modified useSpring hook

const TextAnimate = (direction, index) => useSpring({ 
	from: { 
		transform: `translateY(${direction * 30}vh)` 
	}, 
	to: { 
		transform: "translateY(0vh)" }, 
	delay: 1200 + index * 300, 
	config: { 
		easing: easings.easeCubicInOut, 
		duration: 1200 
	} 
});
// Text splitting for individual animations 

{"Lorem ipsum dolor sit amet,"
	.split(" ")
	.map((item, index) => ( 
		<animated.span className="one" key={index} style={TextAnimate(1, index)}>
		{item}&nbsp;
		</animated.span>
))}

The split() function splits the string into characters using the delimiter passed as the parameter, which in this case is " " character (whitespace character). Which would create an array of words, over which we iterate to create individual elements with their own animations, with the offset passed as the parameter in each iteration to maintain an order of reveal. We use the &nbsp; unicode character to mention a whitespace as any whitespaces mention as a JavaScript literal is discarded.

Giving you the final result as shown

Resources

React Spring Docs - react-spring.io

d3-ease Docs - github.com/d3/d3-ease