Skip to content

Rule · Smoothness

requestAnimationFrame loop runs while idle

smooth/raf-loop-idlewarnvoid smoothupdated

Why it matters

A perpetual rAF loop (canvas, WebGL, JS-driven marquee) burns CPU and battery on every frame even when nothing is visible, and competes with scrolling.

How to fix it

Pause loops when the element is off-screen (IntersectionObserver) or the tab is hidden, and render on demand instead of every frame.

Example

ts
new IntersectionObserver(([e]) => e.isIntersecting ? start() : stop()).observe(canvas);

void smooth reports 13 rules in this category. How the page feels after it loads: dropped frames during a scripted scroll, long animation frames, INP of real clicks, shifts after input, animated layout properties, idle rAF loops and reduced-motion handling.