DEV Community

Saurabh Raj
Saurabh Raj

Posted on

Learn requestAnimationFrame - Never to look back again

What is requestAnimationFrame?

requestAnimationFrame is a browser API that lets you schedule a function to run right before the browser repaints the screen. Think of it as saying "Hey browser, call my function when you're about to draw the next frame."

How Does It Work?

The browser typically repaints the screen 60 times per second (60 FPS), which means every ~16.67 milliseconds. When you call requestAnimationFrame(callback), the browser adds your callback function to a queue and executes it just before the next repaint.

Here's the basic syntax:

function animate() {
    // Your animation code here
    requestAnimationFrame(animate); // Schedule the next frame
}
requestAnimationFrame(animate); // Start the animation
Enter fullscreen mode Exit fullscreen mode

The Browser's Rendering Pipeline

Understanding when requestAnimationFrame fits in helps explain why it's so useful:
1. JavaScript execution (your code runs)

  1. Style calculations (CSS is processed)
  2. Layout (elements are positioned)
  3. Paint (pixels are drawn)
  4. Composite (layers are combined)

requestAnimationFrame callbacks run right before step 2, giving you the perfect timing to make changes that will be included in the current frame.

Why Before Step 2 is Perfect

When your requestAnimationFrame callback runs before step 2, any changes you make (like element.style.left = '100px') get included in the current frame's style calculations.

function animate() {
    // This change happens BEFORE style calculation
    element.style.left = position + 'px';
    // Browser will include this change in the current frame
}
Enter fullscreen mode Exit fullscreen mode

The result: Your animation change appears on screen in this frame cycle.

Why Use requestAnimationFrame?

1. Perfect Timing
Unlike setTimeout or setInterval, which run independently of the browser's refresh rate, requestAnimationFrame is synchronized with the display. This means your animations will be smooth and won't cause visual tearing or stuttering.

2. Automatic Throttling
When a tab becomes inactive (user switches tabs), requestAnimationFrame automatically pauses, saving CPU and battery. setTimeout keeps running regardless.

3. Better Performance
The browser can optimize requestAnimationFrame callbacks by batching DOM changes and coordinating with the GPU.

When Should You Use It?

Perfect For:

  • Smooth animations (moving elements, fading, scaling)
  • Game loops (updating sprites, physics calculations)
  • Data visualizations (updating charts, graphs)
  • Custom scrolling effects
  • Canvas/WebGL rendering

Not Necessary For:

  • CSS transitions/animations (browser handles these automatically)
  • One-time DOM updates (just change the property directly)
  • Non-visual periodic tasks (use setTimeout/setInterval)

Practical Examples

Simple Movement Animation

let position = 0;
const element = document.getElementById('box');

function moveBox() {
    position += 2;
    element.style.transform = `translateX(${position}px)`;

    if (position < 300) {
        requestAnimationFrame(moveBox);
    }
}
requestAnimationFrame(moveBox);
Enter fullscreen mode Exit fullscreen mode

Time-Based Animation (More Robust)

let startTime = null;
const duration = 2000; // 2 seconds
const element = document.getElementById('box');

function animate(currentTime) {
    if (!startTime) startTime = currentTime;
    const elapsed = currentTime - startTime;
    const progress = Math.min(elapsed / duration, 1);

    // Easing function for smooth motion
    const easeProgress = progress * (2 - progress);

    element.style.transform = `translateX(${easeProgress * 300}px)`;

    if (progress < 1) {
        requestAnimationFrame(animate);
    }
}
requestAnimationFrame(animate);
Enter fullscreen mode Exit fullscreen mode

Important Details

Canceling Animations

You can cancel a scheduled animation using the returned ID:

const animationId = requestAnimationFrame(animate);
cancelAnimationFrame(animationId); // Cancel it
Enter fullscreen mode Exit fullscreen mode

Handling Multiple Elements

For multiple animations, use a single requestAnimationFrame loop:

const elements = [element1, element2, element3];

function animateAll() {
    elements.forEach((el, index) => {
        // Update each element
        el.style.transform = `rotate(${Date.now() * 0.01 * (index + 1)}deg)`;
    });
    requestAnimationFrame(animateAll);
}
requestAnimationFrame(animateAll);
Enter fullscreen mode Exit fullscreen mode

Performance Tips

  1. Batch DOM changes within your callback
  2. Use transform and opacity instead of properties that trigger layout.
  3. Consider using Web Animations API for complex animations

Browser Support

requestAnimationFrame is supported in all modern browsers. For older browsers, you can use a polyfill that falls back to setTimeout.

The key takeaway is that requestAnimationFrame gives you the smoothest possible animations by working with the browser's natural refresh cycle rather than against it. It's the standard way to create performant animations in modern web development.

Wrapping up

Thanks for reading! If you’ve made it this far, kudos to you for investing in your personal growth.

If you found this helpful, feel free to like and drop a comment— I’d love to hear your thoughts.

Don’t forget to check out my other articles to keep learning.

Thanks again for your time!

Top comments (0)