React Motion is an animation library for React applications that makes it easy to create and implement realistic animations. In this guide, we’ll demonstrate how to install the library and share some basic tips to help you build natural-looking, physics-based animations for your React projects.
The Replay is a weekly newsletter for dev and engineering leaders.
Delivered once a week, it's your curated guide to the most important conversations around frontend dev, emerging AI tools, and the state of modern software.
Create a new React project by running:
npx create-react-app intro-react-motion
To install React Motion, run the following command inside your project root.
npm i react-motion
The react-motion library exports the following.
spring — A helper function that dictates how the component animatespresets — An object of predefined animation propertiesMotion — A component that is used to animate a componentStaggeredMotion — A component that is used to animate components whose animation depends on each otherTransitionMotion — A component that is used to animate the mount and unmounts of componentsFor the sake of brevity, this guide will focus on spring, presets, and Motion.
spring() and presetsThe spring() helper function defines how to animate from the initial style value to the destination value. It takes in two arguments: the value and an option animation config parameter.
For example, spring(10, { stiffness: 130, damping: 42 }) animates the value to 10 with a stiffness of 130 and damping of 42. stiffness and damping are animation properties that define the animation’s behavior. Don’t worry — it’s normal not to understand how these properties work.
The presets properties are used as the animation configuration. For example, spring(25, presets.wobbly). Other preset values include presets.gentle, presets.noWobble, presets.stiff.
<Motion /> componentThe <Motion /> component takes in two props: defaultStyle and style. The defaultStyle prop defines the initial values of the style object. The style prop is an object that defines the style values at any given point. The values of the style prop are determined using the spring() helper function. If the defaultStyle is the original style, then style is the final style that the components animate to.
The <Motion /> component expects a function as its child prop, which means it uses the render prop pattern. The function receives an interpolated style object, which contains the style value at any given time until the animation is completed.
<<Motion
defaultStyle={{
scale: 0,
translateX: -300
}}
style={{
scale: spring(1),
translateX: spring(0, presets.stiff)
}}
>
{interpolatesStyles => <>{/* React Component */}</>}
</Motion>
Let’s look at a basic example.
At the top of your component file, import Motion, spring, and presets from the react-motion library to use them in your component.
import { Motion, spring, presets } from "react-motion";
Create an <h1> element in the component that will be animated inside App.js.
// ...
function App() {
return (
<div className="App">
<div>
<h1>Basic Animation Example</h1>
</div>
</div>
);
}
// ...
Now wrap your component with the <Motion /> component and return the <h1> component from the render prop function. Pass { opacity: 0, translateY: 30 } in the defaultStyle prop. In the style prop, use the spring() helper function to interpolate the style values.
// ...
<Motion
defaultStyle={{
opacity: 0,
translateY: 30
}}
style={{
opacity: spring(1),
translateY: spring(0, presets.wobbly)
}}
>
{interpolatedStyles => (
<div
style={{
transform: `translateY(${interpolatedStyles.translateY}px)`,
opacity: interpolatedStyles.opacity
}}
>
<h1>Basic Animation Example</h1>
</div>
)}
</Motion>
// ...
Here’s the final code:
import React from "react";
import "./styles.css";
import { Motion, spring, presets } from "react-motion";
function App() {
return (
<div className="App">
<Motion
defaultStyle={{
opacity: 0,
translateY: 30
}}
style={{
opacity: spring(1),
translateY: spring(0, presets.wobbly)
}}
>
{interpolatedStyles => (
<div
style={{
transform: `translateY(${interpolatedStyles.translateY}px)`,
opacity: interpolatedStyles.opacity
}}
>
<h1>Basic Animation Example</h1>
</div>
)}
</Motion>
</div>
);
}
export default App;
Run the following command to see the above code in action.
npm start
The animation will start as soon as the component mounts on to the DOM. Now let’s see how you can also trigger the animation with a button click.
Using state, you can add style dynamically to interpolate the style values. In a variable, store the initial style for the animation.
function App() {
const [startAnimation, setAnimation] = useState(false);
const initialStyle = { opacity: 0, translateY: 30 };
// ...
}
In the <Motion /> component, you don’t have to specify the defaultStyle prop because the style prop is going to change dynamically.
// ...
<Motion
style={
startAnimation
? {
opacity: spring(1),
translateY: spring(0, presets.wobbly)
}
: initialStyle
}
>
{interpolatedStyles => (
<div
style={{
transform: `translateY(${interpolatedStyles.translateY}px)`,
opacity: interpolatedStyles.opacity
}}
>
<h1>Triggered Animation</h1>
</div>
)}
</Motion>
// ...
Add two buttons: one to trigger the animation and another to reset the animation.
// ...
<button onClick={() => setAnimation(true)}>Trigger Animation</button>
<button onClick={() => setAnimation(false)}>Reset Animation</button>
// ...
When the startAnimation state is set to true, the style prop will get the initial style values. When it sets to false, the style prop will have the final values.
Your App.js should look as follows.
import React, { useState } from "react";
import "./styles.css";
import { Motion, spring, presets } from "react-motion";
export default function App() {
const [startAnimation, setAnimation] = useState(false);
const initialStyle = { opacity: 0, translateY: 30 };
return (
<div className="App">
<Motion
style={
startAnimation
? {
opacity: spring(1),
translateY: spring(0, presets.wobbly)
}
: initialStyle
}
>
{interpolatedStyles => (
<div
style={{
transform: `translateY(${interpolatedStyles.translateY}px)`,
opacity: interpolatedStyles.opacity
}}
>
<h1>Triggered Animation</h1>
</div>
)}
</Motion>
<button onClick={() => setAnimation(true)}>Trigger Animation</button>
<button onClick={() => setAnimation(false)}>Reset Animation</button>
</div>
);
}
styled-componentsYou can use react-motion with any other UI library for React. Let’s see how you can use react-motion with the styled-components library.
Install styled-components by running the following command inside your project root.
npm i styled-components
Create the styled <Title /> component as follows.
// ..
import styled from "styled-components";
const Title = styled.h1`
color: #007bff;
font-size: 32px;
${props =>
`transform: translateY(${props.translateY}px);
opacity: ${props.opacity};
`}
`;
// ..
Similar to the above examples, return the <Title /> component from the render prop function. Pass the interpolated values as props to the <Title /> component.
<Motion
style={
startAnimation
? {
opacity: spring(1),
translateY: spring(0, presets.wobbly)
}
: initialStyle
}
>
{interpolatedStyles => (
<Title
opacity={interpolatedStyles.opacity}
translateY={interpolatedStyles.translateY}
>
Triggered Animation
</Title>
)}
</Motion>
Your complete App.js should look as follows.
import React, { useState } from "react";
import "./styles.css";
import { Motion, spring, presets } from "react-motion";
import styled from "styled-components";
const Title = styled.h1`
color: #007bff;
font-size: 32px;
${props =>
`transform: translateY(${props.translateY}px);
opacity: ${props.opacity};
`}
`;
export default function App() {
const [startAnimation, setAnimation] = useState(false);
const initialStyle = { opacity: 0, translateY: 30 };
return (
<div className="App">
<Motion
style={
startAnimation
? {
opacity: spring(1),
translateY: spring(0, presets.wobbly)
}
: initialStyle
}
>
{interpolatedStyles => (
<Title
opacity={interpolatedStyles.opacity}
translateY={interpolatedStyles.translateY}
>
Triggered Animation
</Title>
)}
</Motion>
<button onClick={() => setAnimation(true)}>Trigger Animation</button>
<button onClick={() => setAnimation(false)}>Reset Animation</button>
</div>
);
}
Regardless of which library you are using, react-motion will work as long as the library supports custom styling.
If you encounter errors, depreciated warnings, or things that don’t run as expected, revert to the original versions of these libraries by replacing your dependencies inside package.json file with the following versions.
//...
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.5.0",
"@testing-library/user-event": "^7.2.1",
"react": "^16.13.0",
"react-dom": "^16.13.0",
"react-motion": "^0.5.2",
"react-scripts": "3.4.0",
"styled-components": "^5.0.1"
}
//...
Then run:
npm i
This will install the exact same dependencies on which these examples were tested.
React Motion is one of the easiest animation libraries out there for animating components in React. This was just a brief introduction to the react-motionlibrary. As a next step, I would recommend looking into components such as <StaggeredMotion /> and <TransitionMotion />, which are similar to the <Motion /> component but have an advanced implementation for more complex animations.
Install LogRocket via npm or script tag. LogRocket.init() must be called client-side, not
server-side
$ npm i --save logrocket
// Code:
import LogRocket from 'logrocket';
LogRocket.init('app/id');
// Add to your HTML:
<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>

:has(), with examplesThe CSS :has() pseudo-class is a powerful new feature that lets you style parents, siblings, and more – writing cleaner, more dynamic CSS with less JavaScript.

Kombai AI converts Figma designs into clean, responsive frontend code. It helps developers build production-ready UIs faster while keeping design accuracy and code quality intact.

Discover what’s new in The Replay, LogRocket’s newsletter for dev and engineering leaders, in the October 22nd issue.

John Reilly discusses how software development has been changed by the innovations of AI: both the positives and the negatives.
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up now