After Effects quality without video or GIF
Lottie brings animations designers build in After Effects into the app as a compact JSON file and plays them back natively on iOS and Android, without a video file and without hand-written animation code. This article covers the JSON pipeline, programmatic control through play, pause, and dynamic colors, and where Lottie's limits are compared to hand-coded Reanimated animations.
Table of Contents
- 1. What is Lottie, and how does the JSON pipeline work?
- 2. Setup: installation and a first LottieView
- 3. Programmatic control: play, pause, and speed
- 4. Dynamic colors without editing the JSON file
- 5. Interactivity: tying progress to scroll or a gesture
- 6. Performance characteristics and common bottlenecks
- 7. Limits compared to hand-coded Reanimated animations
- 8. The asset pipeline in practice: export pitfalls
- 9. Practical example: a success checkmark after form submission
- 10. Summary
- 11. FAQ
1. What is Lottie, and how does the JSON pipeline work?
Lottie is a format and rendering library built by Airbnb that exports animations from Adobe After Effects as a JSON file and plays them back natively across platforms. The export runs through the Bodymovin plugin, which translates layers, shapes, paths, and keyframes from After Effects into a declarative JSON description that contains no raster images at all, only pure vector data.
On React Native, lottie-react-native handles parsing and rendering that JSON file by wiring in the native Lottie libraries for iOS and Android under the hood. Playback itself therefore happens natively, comparable to a vector graphic re-interpolated on every frame, not as a played-back video or animated GIF, which results in noticeably smaller file sizes and crisp rendering at any screen size.
2. Setup: installation and a first LottieView
After installing lottie-react-native and doing the required native linking, an animation can be wired up either as a local JSON file through require() or as a remote URL. For production apps, the local variant is usually preferable, since it carries no load time and no dependency on network availability.
The LottieView component handles the entire playback logic: size, looping, and autoplay can be controlled directly through props, while finer control, say deliberately starting after a user event, happens through a ref and imperative methods.
import LottieView from 'lottie-react-native';
function SuccessAnimation() {
return (
<LottieView
source={require('./assets/success-check.json')}
autoPlay
loop={false}
style={{ width: 160, height: 160 }}
/>
);
}
3. Programmatic control: play, pause, and speed
For use cases where an animation should deliberately start or pause at a specific moment, say after a successful form submission, a ref gets attached to the LottieView. Through it, play(), pause(), and reset() can be called imperatively, optionally with a start and end frame to play only a segment of the animation.
Playback speed can be adjusted through the speed prop, which in practice is useful for reusing the same animation file across different contexts, say a faster version for impatient repeat users and a slower one for the first onboarding moment.
function SubmitButton() {
const animationRef = useRef<LottieView>(null);
const [submitting, setSubmitting] = useState(false);
async function handleSubmit() {
setSubmitting(true);
await submitForm();
animationRef.current?.play(0, 60);
}
return (
<LottieView
ref={animationRef}
source={require('./assets/success-check.json')}
loop={false}
autoPlay={false}
onAnimationFinish={() => setSubmitting(false)}
/>
);
}
4. Dynamic colors without editing the JSON file
A common requirement is adapting a Lottie animation delivered by designers to the current brand color or a dark theme, without maintaining a separate JSON file for every variant. Through the colorFilters prop, individual named layers of the animation can be recolored at runtime, provided the layers were given descriptive names in After Effects.
For more complex cases, lottie-react-native also offers a dynamic properties API that lets you override not just colors but also position, size, or opacity of individual layers at runtime, which enables theming or personalized content within the same animation file.
<LottieView
source={require('./assets/onboarding-illustration.json')}
autoPlay
loop
colorFilters={[
{ keypath: 'Primary Shape', color: theme.colors.brandPrimary },
{ keypath: 'Accent Shape', color: theme.colors.brandAccent },
]}
/>
5. Interactivity: tying progress to scroll or a gesture
The progress prop lets you set an animation's playback progress directly instead of playing it automatically. That allows tying animations to user interactions, say a pull-to-refresh indicator whose progress is set proportionally to the pull distance, or a progress display that exactly matches the scroll position of an onboarding screen.
The important caveat is that every update to progress runs through the JS thread, not through a worklet on the UI thread the way Reanimated works. With very frequent updates, say on every pixel of a scroll gesture, that can cause noticeable lag, which is why throttling the update frequency makes sense in such cases.
const [progress, setProgress] = useState(0);
const scrollHandler = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
const ratio = event.nativeEvent.contentOffset.y / MAX_SCROLL;
setProgress(Math.min(Math.max(ratio, 0), 1));
};
<LottieView
source={require('./assets/progress-indicator.json')}
progress={progress}
/>
6. Performance characteristics and common bottlenecks
Lottie renders natively and is fast enough for most everyday animations without developers having to worry about the details. With very complex animations that have many layers, masks, or shapes computed through expressions in After Effects, playback can still generate noticeable CPU load on older devices, since every layer has to be re-interpolated on every frame.
In practice, it helps to simplify animations before export in After Effects: merging shapes, removing unnecessary layers, and replacing expressions with fixed keyframes where possible. The newer dotLottie format also bundles several animations and assets into one compressed file, reducing both bundle size and load time compared to individual JSON files.
7. Limits compared to hand-coded Reanimated animations
Lottie excels at fixed, choreographed, designer-crafted sequences such as success checkmarks, loading animations, or onboarding illustrations, where the motion is predetermined. Once an animation needs to react dynamically to physical input, say a card that follows a finger movement in real time and settles naturally, Lottie hits its limits, because playback stays bound to a pre-recorded timeline.
Reanimated and Skia, by contrast, allow fully code-driven, worklet-based animations that can react to any arbitrary input value in real time, without being tied to a fixed keyframe sequence. The pragmatic rule of thumb: designer-authored, fixed sequences belong to Lottie, physically reactive or data-driven interactions belong to Reanimated or Skia.
8. The asset pipeline in practice: export pitfalls
Not every After Effects feature is supported by Lottie renderers. Certain mask and matte types, some expressions, and a few text layer effects either get ignored by the Bodymovin export or lead to visible differences between the After Effects preview and the actual rendering in the app. Testing the exported file in the LottieFiles preview before integration saves a lot of time here.
When working with a design team, it pays to agree early on a list of supported features and deliberately avoid complex effects Lottie cannot represent, rather than discovering them as a bug only after integrating them into the app.
9. Practical example: a success checkmark after form submission
A complete example combines several of the building blocks shown earlier: the animation only starts after a successful server request, plays once, and triggers navigation to the next screen through onAnimationFinish, without the user having to tap forward manually.
This pattern, animation as confirmation of a completed action rather than pure decoration, is one of the most common and, at the same time, most user-friendly uses of Lottie in production apps.
function SuccessScreen({ onDone }: { onDone: () => void }) {
return (
<LottieView
source={require('./assets/success-check.json')}
autoPlay
loop={false}
speed={1.2}
onAnimationFinish={onDone}
style={{ width: 200, height: 200, alignSelf: 'center' }}
/>
);
}
| Use case | Recommendation | Why | Alternative |
|---|---|---|---|
| Success checkmark after a form | Lottie | Fully designed sequence, no custom code needed | Reanimated for very simple cases |
| Physically reactive gesture | Reanimated | Real-time worklet control required | No sensible Lottie alternative |
| Onboarding illustration | Lottie | Designer workflow through After Effects | Static image on a tight budget |
| Data-driven chart | Skia or Reanimated | Lottie cannot change its structure dynamically | No sensible Lottie alternative |
| Pull-to-refresh indicator | Lottie with progress control | Pre-built motion tied to scroll | Reanimated for full control |
| Loading indicator with brand color | Lottie with colorFilters | One file usable across multiple themes | Custom Reanimated solution |
Mironsoft
React Native app development and Magento integration
A mobile app for the Magento shop that actually runs smoothly?
We build React Native apps cleanly connected to the Magento REST or GraphQL API, from the first line of code to publishing on the App Store and Google Play.
App Concept
Plan the architecture and feature scope of a Magento-connected app together.
Magento API Integration
Cleanly connect product catalog, cart, and checkout to the shop API.
Store Publishing
Guide the App Store and Google Play release process without pitfalls.
10. Summary
Lottie in React Native
Core idea
Lottie plays animations designers build in After Effects natively from compact JSON, without video or GIF.
Control
A ref lets you call play, pause, reset, speed, and progress imperatively.
Dynamic colors
colorFilters recolors named layers at runtime without editing the JSON file.
Limit
Fixed choreographed sequences belong to Lottie, physically reactive interactions belong to Reanimated.