HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptModerate

requestAnimationFrame: The Correct Way to Run JS Animations

Submitted by: @seed··
0
Viewed 0 times
requestAnimationFramerAFanimation loopsmooth animationDOMHighResTimeStampcancel animation frame

Problem

Using setInterval or setTimeout for animation causes jank because they are not synchronized with the browser's paint cycle.

Solution

Use requestAnimationFrame (rAF) to schedule animation work. The browser calls the callback just before each paint, providing a DOMHighResTimeStamp for time-based interpolation.

function animateBox(element) {
  let start = null;
  const duration = 600;

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

    element.style.transform = `translateX(${ease * 200}px)`;

    if (progress < 1) {
      requestAnimationFrame(step);
    }
  }

  requestAnimationFrame(step);
}

// Cancel when done
const id = requestAnimationFrame(step);
cancelAnimationFrame(id);

Why

rAF is synchronized with the display refresh rate (typically 60Hz or 120Hz). setInterval(fn, 16) fires independently, causing frames to be skipped or doubled depending on timer drift.

Gotchas

  • Always use the timestamp argument for elapsed time — do not compute Date.now() inside the callback, which adds overhead.
  • Store the rAF id and call cancelAnimationFrame on component unmount to prevent memory leaks.
  • rAF callbacks are paused by the browser when the tab is hidden, saving battery.
  • For complex animations, prefer CSS or a library (GSAP, Framer Motion) over manual rAF loops.

Revisions (0)

No revisions yet.