Hiprup

What is requestAnimationFrame?

requestAnimationFrame schedules a function to run right before the browser's next repaint, ideal for smooth animations.

  • Synced to display — runs about 60 times per second, matching the screen refresh.

  • Efficient — pauses automatically in background tabs, saving CPU and battery.

Prefer it over setInterval for animation — smoother, and it won't draw frames the user can't see.

// Smooth animation
function animate(element) {
  let start = null;
  const duration = 1000; // 1 second

  function step(timestamp) {
    if (!start) start = timestamp;
    const progress = Math.min((timestamp - start) / duration, 1);

    element.style.transform = `translateX(${progress * 300}px)`;
    element.style.opacity = 1 - progress;

    if (progress < 1) {
      requestAnimationFrame(step); // Continue animation
    }
  }

  requestAnimationFrame(step); // Start animation
}

// Cancel animation
const id = requestAnimationFrame(myAnimation);
cancelAnimationFrame(id); // Stop

// Smooth scroll position tracking
function onScroll() {
  const scrollY = window.scrollY;
  updateHeader(scrollY);
  requestAnimationFrame(onScroll); // Loop
}
requestAnimationFrame(onScroll);

requestAnimationFrame calls step before each repaint (~16ms for 60fps). The timestamp parameter enables time-based animations (progress = elapsed/duration).

The animation continues by calling requestAnimationFrame recursively. cancelAnimationFrame stops the loop. The scroll tracking example creates a 60fps loop for smooth header updates.

requestAnimationFrame over setInterval for animations: syncs with display refresh, pauses in hidden tabs, and no jank. The timestamp parameter enables time-based animations (not frame-count based). cancelAnimationFrame for cleanup.

This is the correct API for any visual JavaScript animation.