With naturally fluid animations you will elevate your UI & interactions. Bringing your apps to life has never been simpler.
npm i @react-spring/web
Why Springs?
We think of animation in terms of time and curves, but that causes most of the struggle we face when trying to make elements on the screen move naturally, because nothing in the real world moves like that. Springs don’t have a defined curve or a set duration.
As Andy Matuschak (ex Apple UI-Kit developer) expressed – “Animation APIs parameterized by duration and curve are fundamentally opposed to continuous, fluid interactivity.”
Hear what our fans say
![Ryan Florence](/images/quotee/ryan_florence.jpeg)
Remix Co-founder
Holy smokes. I don't think animation can get any easier in React now with React Spring. Wrapping Reach UI (https://reach.tech/ui) in your own brand and feel is going to be so easy.
![Ives van Hoorne](/images/quotee/ives_van_hoorne.jpeg)
Creator of Codesandbox
Big fan of React Spring!
![Alexander Prinzhorn](/images/quotee/alexander_prinzhorn.jpeg)
Software Engineer
react-spring is insane. I haven't done a lot of animations but it's the first React library I come across that does it the correct way: not using setState to change styles but bypass React.
![Josh W. Comeau](/images/quotee/josh_w._comeau.jpeg)
Creator of CSS for JavaScript Developers
It's fantastic :) In my React Rally talk, I explicitly recommend it over React Motion, and all the demos use it (shout-out to @0xca0a). Will share a link to it once the talk vid is up.
![Pierre Bertet](/images/quotee/pierre_bertet.jpeg)
Software Engineer
If you like react-motion but feel like your transitions aren’t smooth, it’s because it’s exclusively using React rendering. If you like Popmotion but feel like you are limited by what you can do, it’s because it entirely skips React rendering. react-spring does both, try it 👌
![//](/images/quotee/no_name.jpeg)
Engineer at Airbnb
react-spring by @0xca0a is a lovely animation library for react
![bruno lemos](/images/quotee/bruno_lemos.jpeg)
Software Engineer
The animation lib React Spring is so awesome! Great API (first-class support for hooks), performant (doesn't trigger a re-render) and cross-platform (web / react-native / universal). Adding animations makes the app much more fun to use.
![arzafran](/images/quotee/arzafran.png)
Partner at Studio Freight
this would’ve been impossible without the hard work from everyone at @pmndrs, zustand, r3f, react-spring, and obviously @clementroche_‘s incredible talent. but it was no easy task to learn all the tricks we now know.. and thinking about all the stuff we still don’t
![Varun Vachhar](/images/quotee/varun_vachhar.jpeg)
Software Engineer
So, it turns out you can mix HTML and WebGL. And with react-spring you can animate both.
![Alex Stanislawski](/images/quotee/alex_stanislawski.jpeg)
Software Engineer
The game being game, I have a lot of animations. I started using what is proposed by tailwind but it is not good enough for 2020. I ended moving to react spring. The learning curve is steeper than what I had expect. But it's a delightful experience afterwards.
But wait, there’s more
It’s not just for web
Choose from our five targets:
- web
- native
- three
- konva
- zdog
Missing a target you want? Request we add it or create it yourself with our advanced API usage.
import { animated, useSpring } from '@react-spring/web'
export const MyComponent = () => {
const { x } = useSpring({
from: {
x: 0,
},
to: {
x: 1,
},
})
return <animated.div style={{ x }} />
}
Avoid unnecessary overhead
Run animations without re-rendering
Use our imperative API methods to run animations without updating state. Respond to events without the react rendering overhead to achieve smooth, fluid animation.
Designed with you in mind
Production ready with SSR support
Forget about useRef & useEffect to attach your animations to dom nodes. animated takes care of it for you.
Fully written in Typescript for easy integration to your pre-existing codebase.
Use a target for a small bundle size or omit the target and just use the core for an even smaller package.
55.1kb
react-spring
19.2kb
web
15.2kb
core
Wow, that's a lot!
And there's even more
- Animate any value – strings, numbers, css variables...
- Shorthand transformation styles
- Interpolate values inline
- Easily react to animation events
- Usable with any component library
import * as Dialog from '@radix-ui/react-dialog'import { styled } from '@stitches/react'import { animated, useSpring } from '@react-spring/web'export const AnimatedDialog = ({ isOpen, onOpenCallback }) => {const { x, backgroundColor, o } = useSpring({x: isOpen ? '0%' : '-100%',backgroundColor: isOpen? 'var(--color-whiteblur)': 'var(--colors-white00)',o: isOpen ? 1 : 0,onRest: () => {if (isOpen && onOpenCallback) {onOpenCallback()}},})return (<Dialog.Root><Overlay style={{ backgroundColor }} /><Modal style={{ x, backgroundColor: o.to(o => 'rgba(255,255,255,' + o + ')'), }} /></Dialog.Root>)}
import * as Dialog from '@radix-ui/react-dialog'import { styled } from '@stitches/react'import { animated, useSpring } from '@react-spring/web'export const AnimatedDialog = ({ isOpen, onOpenCallback }) => {const { x, backgroundColor, o } = useSpring({x: isOpen ? '0%' : '-100%',backgroundColor: isOpen? 'var(--color-whiteblur)': 'var(--colors-white00)',o: isOpen ? 1 : 0,onRest: () => {if (isOpen && onOpenCallback) {onOpenCallback()}},})return (<Dialog.Root><Overlay style={{ backgroundColor }} /><Modal style={{ x, backgroundColor: o.to(o => 'rgba(255,255,255,' + o + ')'), }} /></Dialog.Root>)}
import * as Dialog from '@radix-ui/react-dialog'import { styled } from '@stitches/react'import { animated, useSpring } from '@react-spring/web'export const AnimatedDialog = ({ isOpen, onOpenCallback }) => {const { x, backgroundColor, o } = useSpring({x: isOpen ? '0%' : '-100%',backgroundColor: isOpen? 'var(--color-whiteblur)': 'var(--colors-white00)',o: isOpen ? 1 : 0,onRest: () => {if (isOpen && onOpenCallback) {onOpenCallback()}},})return (<Dialog.Root><Overlay style={{ backgroundColor }} /><Modal style={{ x, backgroundColor: o.to(o => 'rgba(255,255,255,' + o + ')'), }} /></Dialog.Root>)}
import * as Dialog from '@radix-ui/react-dialog'import { styled } from '@stitches/react'import { animated, useSpring } from '@react-spring/web'export const AnimatedDialog = ({ isOpen, onOpenCallback }) => {const { x, backgroundColor, o } = useSpring({x: isOpen ? '0%' : '-100%',backgroundColor: isOpen? 'var(--color-whiteblur)': 'var(--colors-white00)',o: isOpen ? 1 : 0,onRest: () => {if (isOpen && onOpenCallback) {onOpenCallback()}},})return (<Dialog.Root><Overlay style={{ backgroundColor }} /><Modal style={{ x, backgroundColor: o.to(o => 'rgba(255,255,255,' + o + ')'), }} /></Dialog.Root>)}
import * as Dialog from '@radix-ui/react-dialog'import { styled } from '@stitches/react'import { animated, useSpring } from '@react-spring/web'export const AnimatedDialog = ({ isOpen, onOpenCallback }) => {const { x, backgroundColor, o } = useSpring({x: isOpen ? '0%' : '-100%',backgroundColor: isOpen? 'var(--color-whiteblur)': 'var(--colors-white00)',o: isOpen ? 1 : 0,onRest: () => {if (isOpen && onOpenCallback) {onOpenCallback()}},})return (<Dialog.Root><Overlay style={{ backgroundColor }} /><Modal style={{ x, backgroundColor: o.to(o => 'rgba(255,255,255,' + o + ')'), }} /></Dialog.Root>)}