📅 Day 15
💡 tip

Reanimated 4: CSS Animations Made Simple

Learn how Reanimated 4 brings familiar CSS transitions and animations to React Native for powerful, easy-to-implement animations

ReanimatedAnimations

Welcome to Day 15 of the React Native Advent Calendar!

Today we’re diving into Reanimated 4 - a game-changer that brings familiar CSS transitions and animations to React Native. If you’ve ever animated on the web, you’ll feel right at home!


What’s New in Reanimated 4?

Reanimated 4 was released in 2025 with major improvements, but the real star of the show is CSS-style animations. Instead of complex imperative animation code, you can now use CSS properties you already know:

  • CSS Transitions - Animate style changes automatically
  • CSS Animations - Define keyframes for complex sequences
  • Familiar syntax - Works just like web CSS animations

Why it matters: Less code, easier maintenance, and faster development. Simple animations that took 20+ lines now take just 3!


CSS Transitions: The Quick Win

Transitions automatically animate property changes. Perfect for hover effects, state changes, and simple interactions.

Button.tsx
import { View, Text, Pressable } from 'react-native';
import Animated from 'react-native-reanimated';

export default function AnimatedButton() {
	const [isPressed, setIsPressed] = useState(false);

	return (
		<Pressable onPressIn={() => setIsPressed(true)} onPressOut={() => setIsPressed(false)}>
			<Animated.View
				style={{
					backgroundColor: isPressed ? '#3b82f6' : '#6366f1',
					padding: 16,
					borderRadius: 8,
					// Magic happens here:
					transitionProperty: 'backgroundColor',
					transitionDuration: 300,
					transitionTimingFunction: 'ease-in-out'
				}}
			>
				<Text style={{ color: 'white' }}>Press Me</Text>
			</Animated.View>
		</Pressable>
	);
}

That’s it! When backgroundColor changes, Reanimated automatically animates it. No useAnimatedStyle, no worklets - just CSS properties.

Available Transition Properties

  • transitionProperty - Which styles to animate ('backgroundColor', 'transform', etc.)
  • transitionDuration - Animation length in milliseconds
  • transitionDelay - Wait time before starting (in ms)
  • transitionTimingFunction - Easing ('ease', 'linear', 'ease-in-out', etc.)
  • transitionBehavior - How to handle discrete properties

CSS Animations: The Power Move

For complex sequences, use CSS animations with keyframes. Perfect for looping animations, multi-step effects, and attention-grabbers.

PulsingHeart.tsx
import Animated from 'react-native-reanimated';
import { View } from 'react-native';

export default function PulsingHeart() {
	return (
		<Animated.View
			style={{
				width: 100,
				height: 100,
				backgroundColor: '#ef4444',
				borderRadius: 50,
				// Define the animation:
				animationName: keyframes.pulse,
				animationDuration: 1000,
				animationIterationCount: 'infinite',
				animationTimingFunction: 'ease-in-out'
			}}
		/>
	);
}

// Define keyframes
const keyframes = {
	pulse: {
		'0%': { transform: [{ scale: 1 }] },
		'50%': { transform: [{ scale: 1.2 }] },
		'100%': { transform: [{ scale: 1 }] }
	}
};

Available Animation Properties

  • animationName - References your keyframe definition
  • animationDuration - How long one cycle lasts (in ms)
  • animationDelay - Wait before starting (in ms)
  • animationTimingFunction - Easing function
  • animationDirection - Play forwards, backwards, or alternate
  • animationIterationCount - Number of repeats (or 'infinite')
  • animationFillMode - Style persistence before/after animation
  • animationPlayState - 'running' or 'paused'

Real-World Example: Loading Spinner

Here’s a practical example combining multiple properties:

Spinner.tsx
import Animated from 'react-native-reanimated';
import { View } from 'react-native';

export default function Spinner() {
	return (
		<View style={{ padding: 20 }}>
			<Animated.View
				style={{
					width: 40,
					height: 40,
					borderWidth: 4,
					borderColor: '#3b82f6',
					borderTopColor: 'transparent',
					borderRadius: 20,
					animationName: keyframes.spin,
					animationDuration: 800,
					animationIterationCount: 'infinite',
					animationTimingFunction: 'linear'
				}}
			/>
		</View>
	);
}

// Keyframe definition
const keyframes = {
	spin: {
		'0%': { transform: [{ rotate: '0deg' }] },
		'100%': { transform: [{ rotate: '360deg' }] }
	}
};

Result: A smooth, infinite spinner in just a few lines!


Learn by Example

Software Mansion created an example repository with tons of CSS animation demos:

react-native-css-animations - Includes:

  • Bounce effects
  • Fade animations
  • Slide transitions
  • Complex keyframe sequences
  • Loading indicators
  • And much more!

When to Use CSS Animations

Use CSS animations for:

  • Simple property transitions
  • Keyframe-based sequences
  • Looping animations
  • Familiar web-like patterns

Use JavaScript animations (useAnimatedStyle) for:

  • Gesture-driven animations
  • Complex interactive sequences
  • Dynamic values from sensors
  • Fine-grained control over timing

Both approaches work together - use what fits your use case!


Wrapping Up

Reanimated 4’s CSS animations make simple animations trivial and complex ones manageable. The familiar CSS syntax means less learning curve and faster development.

Quick recap:

  1. Install react-native-reanimated 4.x
  2. Use transitionProperty for automatic transitions
  3. Use animationName + keyframes for sequences
  4. Check the example repo for inspiration

Want to dive deeper?

Built something cool with CSS animations? Share it on Twitter!

Tomorrow we’ll explore Day 16’s topic - see you then! 🎄