Animations can greatly enhance the user experience of web applications by adding visual flair and smooth transitions between interface states. In React apps, developers often reach for JavaScript to power animations via popular libraries like Framer Motion or React Spring. However, for many animation use cases, CSS animations offers notable advantages over JavaScript that can optimize performance and provide buttery smooth 60fps visuals.

In this article, we’ll compare CSS animations and JS animations in the context of React performance apps, analyzing the relative merits of each approach. We’ll discover why you may want to choose native CSS for animations more often, especially for subtle micro-interactions.

The Case for CSS Animations

CSS animations delegate the animation logic completely to the browser, avoiding expensive JavaScript work on each frame. This leads to lower CPU usage, higher FPS, and a smoother user experience especially on lower powered devices. Here are some specific advantages of using CSS instead of JavaScript for animations in React apps:

Performance

CSS animations leverage hardware acceleration in the browser and can reach silky smooth 60 FPS animations more easily. JavaScript-powered animations require executing JS on every frame which takes up the main thread and reduces FPS.

For example, animating an element from 0px to 100px over 0.5s with CSS is as simple as:

.my-element {
  animation: slideIn 0.5s ease-out; 
}

@keyframes slideIn {
  from {
    transform: translateX(0);
  }
  to {
    transform: translateX(100px); 
  }
}

Whereas complex JavaScript animation libraries have to recalculate styles and update properties each frame.

Lower Memory Usage

CSS animations have a smaller memory footprint since they avoid creating timer intervals, events listeners and closure scopes like JS animations. This frees up resources for other application code.

Declarative Setup

Describing animations using CSS @keyframes and animation properties allows you to declaratively define animations separate from component code. This abstracts away animation logic from components for better reusability and organization.

Leveraging the Cascade

The cascading nature of CSS makes it straightforward to create variants of the same animation for different contexts. For example, just changing animation duration or delay for hover and active states is trivial with CSS.

Easy Reverse Animations

The css animation-direction property allows you to seamlessly reverse animations for rollback transitions with no extra logic.

Familiar Syntax

Most developers are already familiar with CSS syntax for basic transforms, transitions and keyframes animations. These core APIs allow you to prototype and iterate quickly without learning complex animation libraries.

When to Use JavaScript Instead

While CSS excels at typical UI animations like transitions, subtle micro-interactions and declarative sequenced animations, more advanced use cases require heavier logic that CSS cannot provide.

Here are some examples where you’d still want to use JavaScript for animations:

Complex Sequencing Logic

If you need to programmatically sequence a timeline of animations with dynamic delays, durations and conditional logic, JavaScript libraries like Framer Motion shine. They allow declaring animations imperatively alongside component logic.

Physics-Based Animations

Realistic springs, friction and physics are difficult to model with plain CSS. JavaScript animation libraries like React Spring are ideal for these advanced physics-driven animations.

Component Orchestration

Coordinate multiple components to animate in sequence, for example, animating cards in a scrolling carousel. JavaScript allows referring to components and controlling their animations declaratively.

Interaction with Component State

Animate based on changes in component state like network data loading or validation errors. CSS alone cannot access component state data directly.

Optimizing CSS Animations in React

While CSS animations have innate performance advantages, you still need to be mindful of potential pitfalls for buttery smooth animations:

Use Will-Change

Set will-change: transform/opacity on animated elements to hint browser about forthcoming animations and optimize accordingly.

.animated-element {
   will-change: transform; 
}
⚠️ Warning: The use of will-change should be approached as a final recourse, reserved exclusively for addressing current performance bottlenecks. It’s not a tool to preemptively tackle potential performance issues.

Avoid Forced Synchronized Layouts

Setting layout triggering styles like width, height, top, bottom etc. mid-animation can disrupt rendering. Apply these styles before animations start or use transforms instead.

Prefetch Before Animations

Consider prefetching images that come into view after animations to avoid jank from loading while animating. Eg. use next/image in React performance.

Use CSS Variables

Take animations values like durations, delays and easing curves outside the animation declaration as CSS variables. This prevents creating new computed keyframes each usage.

Hardware Accelerate Elements

For layers backed by GPU, enable hardware acceleration with transform: translateZ(0); where possible for better FPS.

React Animation Examples

Let’s look at some practical examples that use native CSS capabilities for animations in React apps.

Transition on Hover

Subtle hover transition animations on buttons, cards and other components use CSS transition property:

export default function HoverAnimation() {

  return (
    <button 
      className="animate"
      onClick={() => console.log('Clicked!')}
    >
      Hover over me! 
    </button>
  );
}


// Styles
.animate {
  transition: box-shadow 0.3s ease, transform 0.2s ease; 
}

.animate:hover {
  box-shadow: 0 2px 20px rgba(0,0,0,0.2);
  transform: translateY(-4px);
}

Loading Indicator Animation

Animate SVG loaders using CSS keyframe animations:

export default function Loader() {
  return (
    <svg className="loader">
     <circle cx="25" cy="25" r="20"></circle>
    </svg>
  );
}

// Styles
.loader circle {
  animation: rotate 1s linear infinite;
}

@keyframes rotate {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); } 
}

Sequence Animations

Chain animation sequences using animation-delay and animation-fill-mode properties:

.seq-animation {
  animation: slideUp 0.5s ease-out, 
             activeState 0.2s ease-in;
  animation-fill-mode: forwards; 
  animation-delay: 0s, 0.5s; 
}

@keyframes slideUp {
  0% { transform: translateY(50px); }
  100% { transform: translateY(0); }
}

@keyframes activeState {
  0% { transform: scale(1); } 
  100% { transform: scale(1.1); }
}

This first slides the element up, then scales it larger once the slide finishes.

The Order of Operations Matters!

As you explore combining CSS animations, transitions, transforms and keyframe animations in creative ways, one key rule of thumb is to sequence animation declarations correctly in your stylesheets.

The correct order is:

  1. Keyframes
  2. Animation
  3. Transition
  4. Transform

Getting this order right avoids unexpected behavior and promotes smooth 60fps animations.

CSS First, JavaScript Later

Animations are a great way to elevate user experiences in React applications. With its performance advantages and easy learning curve, CSS animations should be the first tool you reach for to animate most typical use cases like hover effects, micro-interactions, SVG loaders, sequenced movements and page transitions.

Reserve more complex animation logic using libraries like Framer and React Spring for advanced physics, imprecise sequencing and orchestrating timelines across many components.

By understanding the strengths of both approaches, you can create delightful animations in React apps using intuitive CSS animations while avoiding performance pitfalls.

Ready to build high quality frontend apps?

I hope this guide gave you clarity on optimizing animations in your React projects. I specialize in building complex React-based user interfaces for startups.

If you have an ambitious web app idea and are looking for an experienced partner, contact me to schedule a consultation call. I’d be happy to provide my insights and estimate costs for your project.