Performance and DevTools

Use requestAnimationFrame for visual updates

Schedule work that changes the current frame near the browser’s next rendering opportunity.

8 minute lesson

~~~

requestAnimationFrame() asks the browser to run a callback before a future paint. It is a good place to apply a visual state that should be synchronized with rendering.

let start

function move(timestamp) {
  start ??= timestamp

  const elapsed = timestamp - start
  const x = Math.min(elapsed / 4, 300)

  box.style.transform = `translateX(${x}px)`

  if (x < 300) requestAnimationFrame(move)
}

requestAnimationFrame(move)

Use the callback timestamp rather than assuming a fixed number of frames per second. Displays have different refresh rates, frames can be delayed, and browsers usually reduce or pause callbacks in background tabs.

requestAnimationFrame does not make expensive work fast. A callback that runs too long still delays the frame. Keep it focused on the state needed for that paint, and move unrelated work elsewhere.

For repeated events such as scroll, store the latest input and schedule at most one pending frame:

let scheduled = false

window.addEventListener('scroll', () => {
  if (scheduled) return
  scheduled = true

  requestAnimationFrame(() => {
    updateHeader(window.scrollY)
    scheduled = false
  })
})

Record the animation with the Performance panel. Check frame timing and the duration of each callback. If frames remain late, investigate the callback and the rendering it triggers instead of adding another scheduling layer.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →