react-transition-group vs framer-motion vs react-native-reanimated vs react-spring vs lottie-react-native vs react-native-animatable
Animation Libraries for React and React Native Applications
react-transition-groupframer-motionreact-native-reanimatedreact-springlottie-react-nativereact-native-animatableSimilar Packages:
Animation Libraries for React and React Native Applications

framer-motion, react-spring, and react-transition-group are animation libraries primarily used in React web applications, while lottie-react-native, react-native-animatable, and react-native-reanimated target React Native. These packages enable developers to implement declarative, performant, and complex animations — from simple fades and transitions to gesture-driven interactions and vector-based Lottie animations. Each library adopts a different mental model: some emphasize physics-based motion (react-spring), others focus on production-ready UI transitions (framer-motion, react-transition-group), and several prioritize native-thread performance in mobile contexts (react-native-reanimated). Choosing the right tool depends heavily on platform (web vs. native), animation complexity, performance requirements, and developer ergonomics.

Npm Package Weekly Downloads Trend
3 Years
Github Stars Ranking
Stat Detail
Package
Downloads
Stars
Size
Issues
Publish
License
react-transition-group21,809,24510,256244 kB244-BSD-3-Clause
framer-motion13,748,03530,4872.34 MB3198 days agoMIT
react-native-reanimated2,493,55610,4993.89 MB3145 days agoMIT
react-spring925,93428,9938.36 kB1343 months agoMIT
lottie-react-native815,52217,084289 kB133 months agoApache-2.0
react-native-animatable621,5759,94659.8 kB1702 years agoMIT

Animation Libraries Compared: Framer Motion, Reanimated, React Spring, and More

When building modern React or React Native apps, choosing the right animation library can make the difference between janky interactions and fluid, engaging experiences. The six packages under review serve overlapping but distinct purposes — some are web-only, others native-only, and a few span both. Let’s cut through the noise and compare them based on real engineering trade-offs.

🖥️ Platform Support: Web vs. React Native

Not all animation libraries work everywhere. This is the first filter.

framer-motion, react-spring, and react-transition-group are designed for React web. While react-spring has experimental React Native support, its primary strength is on the web.

lottie-react-native, react-native-animatable, and react-native-reanimated are React Native–only. They rely on native modules and won’t work in browser environments.

⚠️ Important: Don’t try to share animation logic across platforms using these libraries unless you abstract behind a custom hook or component layer. Their APIs and threading models are fundamentally different.

🎯 Animation Model: Declarative vs. Imperative vs. Physics-Based

Simple Enter/Exit Transitions

For basic show/hide or mount/unmount animations, react-transition-group is purpose-built:

// react-transition-group
import { CSSTransition } from 'react-transition-group';

function Fade({ children, in: inProp }) {
  return (
    <CSSTransition in={inProp} timeout={300} classNames="fade">
      {children}
    </CSSTransition>
  );
}

// Requires corresponding CSS:
// .fade-enter { opacity: 0; }
// .fade-enter-active { opacity: 1; transition: opacity 300ms; }

react-native-animatable offers similar simplicity on native:

// react-native-animatable
import Animatable from 'react-native-animatable';

<Animatable.View animation="fadeIn" duration={300}>
  <Text>Hello</Text>
</Animatable.View>

But note: react-native-animatable runs on the JavaScript thread, so it can stutter under load.

Physics-Based Motion

react-spring uses spring physics instead of fixed durations:

// react-spring (web)
import { useSpring, animated } from 'react-spring';

function MyComponent() {
  const props = useSpring({ opacity: 1, from: { opacity: 0 } });
  return <animated.div style={props}>Hello</animated.div>;
}

It also works on React Native with minor syntax changes:

// react-spring (React Native)
import { useSpring, animated } from 'react-spring/native';

const AnimatedView = animated(View);

function MyNativeComponent() {
  const props = useSpring({ opacity: 1, from: { opacity: 0 } });
  return <AnimatedView style={props}><Text>Hello</Text></AnimatedView>;
}

High-Level Declarative (Web)

framer-motion abstracts even further:

// framer-motion
import { motion } from 'framer-motion';

<motion.div
  initial={{ opacity: 0 }}
  animate={{ opacity: 1 }}
  transition={{ duration: 0.3 }}
>
  Hello
</motion.div>

It handles layout measurements, drag constraints, and even shared-element transitions between routes with minimal code.

Native-Thread Performance (React Native)

react-native-reanimated requires writing "worklets" — functions that run on the UI thread:

// react-native-reanimated
import { useSharedValue, useAnimatedStyle, withTiming } from 'react-native-reanimated';

function ReanimatedBox() {
  const opacity = useSharedValue(0);

  const style = useAnimatedStyle(() => {
    return { opacity: opacity.value };
  });

  // Trigger later
  opacity.value = withTiming(1, { duration: 300 });

  return <Animated.View style={style} />;
}

This avoids the JS-to-native bridge, enabling smooth animations even during heavy computation.

Pre-Rendered Vector Animations

lottie-react-native plays designer-created JSON files:

// lottie-react-native
import LottieView from 'lottie-react-native';

<LottieView
  source={require('./animation.json')}
  autoPlay
  loop
/>

No runtime animation logic — just playback control.

⚙️ Performance Characteristics

  • react-transition-group: Zero runtime cost beyond class toggling. Performance depends entirely on your CSS.
  • react-native-animatable: Runs on JavaScript thread — can drop frames under load. Not suitable for critical UI.
  • react-spring: Uses requestAnimationFrame on web; on native, it animates via native drivers but still communicates over the bridge (unless using v9+ with Reanimated backend).
  • framer-motion: Optimized for web, uses hardware acceleration, but complex layout animations can trigger reflows.
  • react-native-reanimated: Animations run on UI thread — no bridge involvement. Best-in-class performance for React Native.
  • lottie-react-native: Renders vector paths natively. Performance is excellent for moderate-complexity animations but can struggle with very dense Lottie files.

🔁 Gesture and Scroll Integration

Need animations tied to user input?

  • framer-motion supports drag out of the box:
<motion.div drag dragConstraints={{ left: 0, right: 0 }} />
  • react-spring integrates with @use-gesture for pan, pinch, etc.

  • react-native-reanimated pairs with react-native-gesture-handler for seamless gesture-driven animations:

import { PanGestureHandler } from 'react-native-gesture-handler';
import { useAnimatedGestureHandler } from 'react-native-reanimated';

const gestureHandler = useAnimatedGestureHandler({
  onStart: (_, ctx) => { /* ... */ },
  onActive: (event, ctx) => { translateX.value = event.translationX; },
});

The other libraries lack deep gesture integration.

🧩 Code Maintainability and Learning Curve

  • Easiest: react-transition-group and react-native-animatable — just pass strings or props.
  • Moderate: framer-motion and react-spring — require understanding hooks and animation props, but APIs are intuitive.
  • Steepest: react-native-reanimated — demands familiarity with shared values, worklets, and thread boundaries. Mistakes lead to silent failures or crashes.
  • Specialized: lottie-react-native — trivial to use if you have Lottie files; irrelevant otherwise.

🛑 Maintenance and Future-Proofing

As of 2024:

  • react-native-animatable has not seen significant updates in years. While not officially deprecated, it’s effectively in maintenance mode. New projects should evaluate react-native-reanimated or react-native’s built-in Animated API instead.
  • All other libraries are actively maintained with regular releases.

📊 Summary Table

PackagePlatformThreadingBest ForLearning Curve
framer-motionWebMain + GPUDeclarative UI animations, layout transitionsLow-Moderate
lottie-react-nativeReact NativeNativePlaying designer-created vector animationsLow
react-native-animatableReact NativeJavaScriptSimple entrance animations (legacy use)Low
react-native-reanimatedReact NativeUI ThreadHigh-performance, gesture-driven animationsHigh
react-springWeb (+ Native)rAF / BridgePhysics-based, cross-platform animationsModerate
react-transition-groupWebCSS-onlyMount/unmount transitions with CSSLow

💡 Final Guidance

  • Building a React web app? Start with framer-motion for most cases. Fall back to react-transition-group if you’re deeply invested in CSS transitions, or react-spring if you love spring physics.
  • Building a React Native app? Use react-native-reanimated for anything performance-sensitive or interactive. Use lottie-react-native only when you have Lottie assets from designers. Avoid react-native-animatable in new projects.
  • Need cross-platform consistency? react-spring is your only real option — but expect to write platform-specific wrappers for complex cases.

Animation is one area where the “right” tool depends entirely on your specific constraints. There’s no universal winner — only the best fit for your team, platform, and performance budget.

How to Choose: react-transition-group vs framer-motion vs react-native-reanimated vs react-spring vs lottie-react-native vs react-native-animatable
  • react-transition-group:

    Choose react-transition-group for simple, lifecycle-driven enter/exit animations in React web apps — especially when integrating with CSS transitions or keyframes. It doesn’t animate values directly but instead manages DOM state (e.g., adding/removing classes) during component mounting/unmounting. Best suited for modal fades, route transitions, or list item additions/removals where you already have CSS-defined animations and just need reliable lifecycle hooks.

  • framer-motion:

    Choose framer-motion for React web projects that need expressive, production-grade animations with minimal boilerplate. It excels at layout transitions, drag interactions, and shared element animations between routes or components. Its high-level API abstracts away much of the complexity of managing animation state, making it ideal for teams prioritizing developer velocity without sacrificing visual polish.

  • react-native-reanimated:

    Choose react-native-reanimated for high-performance, gesture-driven, or complex interactive animations in React Native. By running animation logic on the UI thread (via worklets), it avoids JavaScript-to-native bridge bottlenecks, enabling buttery-smooth 60+ FPS animations even during heavy JS load. It’s the go-to for bottom sheets, custom sliders, scroll-linked effects, and any animation tied to user input — but comes with a steeper learning curve due to its imperative and functional programming model.

  • react-spring:

    Choose react-spring when you want physics-based, spring-driven animations that feel natural and responsive across both web and React Native. It uses a shared core that works consistently across platforms and supports advanced interpolation, trailing effects, and async orchestration. Ideal for teams comfortable with hooks and reactive patterns who need fine-grained control over animation curves and timing without dropping down to raw CSS or native APIs.

  • lottie-react-native:

    Choose lottie-react-native when you need to render pre-designed, vector-based animations exported from Adobe After Effects via Bodymovin. It’s perfect for loading indicators, onboarding sequences, or branded micro-interactions where design fidelity matters more than runtime control. Avoid if you need dynamic, code-driven animations — Lottie is best for static or parameterized playback of designer-created assets.

  • react-native-animatable:

    Choose react-native-animatable for simple, declarative entrance/exit animations in React Native apps with low performance demands. It provides a straightforward API for common effects like fade, slide, bounce, and flip using JavaScript-thread animations. However, it should be avoided in performance-critical scenarios since it doesn’t leverage the native thread, and the project has seen minimal recent activity — consider it only for lightweight use cases or legacy maintenance.

README for react-transition-group

react-transition-group npm

ATTENTION! To address many issues that have come up over the years, the API in v2 and above is not backwards compatible with the original React addon (v1-stable).

For a drop-in replacement for react-addons-transition-group and react-addons-css-transition-group, use the v1 release. Documentation and code for that release are available on the v1-stable branch.

We are no longer updating the v1 codebase, please upgrade to the latest version when possible

A set of components for managing component states (including mounting and unmounting) over time, specifically designed with animation in mind.

Documentation

TypeScript

TypeScript definitions are published via DefinitelyTyped and can be installed via the following command:

npm install @types/react-transition-group

Examples

Clone the repo first:

git@github.com:reactjs/react-transition-group.git

Then run npm install (or yarn), and finally npm run storybook to start a storybook instance that you can navigate to in your browser to see the examples.