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
The Browser's Rendering Pipeline
Understanding when requestAnimationFrame
fits in helps explain why it's so useful:
1. JavaScript execution (your code runs)
- Style calculations (CSS is processed)
- Layout (elements are positioned)
- Paint (pixels are drawn)
- 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
}
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);
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);
Important Details
Canceling Animations
You can cancel a scheduled animation using the returned ID:
const animationId = requestAnimationFrame(animate);
cancelAnimationFrame(animationId); // Cancel it
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);
Performance Tips
- Batch DOM changes within your callback
- Use transform and opacity instead of properties that trigger layout.
- 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)