Skip to main content

Animation frame budget of 16ms maintained

ab-002048 · performance-deep-dive.regression-prevention.animation-frame-budget
Severity: infoactive

Why it matters

At 60fps, each animation frame has a 16ms budget. Any JavaScript that runs synchronously inside a frame — including a setInterval callback or a DOM layout read followed by a write — can consume that budget entirely, causing the browser to skip the frame and produce visible stutter. ISO 25010:2011 time-behaviour captures the responsiveness requirement; the user-visible failure is an animation that stutters at irregular intervals, particularly during scroll or on lower-powered devices.

Severity rationale

Info because frame-budget violations produce cosmetic jank rather than functional failures — they are worth fixing for polish and accessibility but do not prevent users from completing tasks.

Remediation

Replace setInterval-driven animations with CSS transitions or requestAnimationFrame. For values that animate over time, CSS transform and opacity are GPU-composited and do not trigger layout.

/* components/animated-card.module.css — GPU-composited animation */
.card {
  transition: transform 0.25s ease, opacity 0.25s ease;
  will-change: transform;  /* hint GPU layer promotion */
}

.card:hover {
  transform: translateY(-4px);
}

For JS-driven values, schedule work with requestAnimationFrame rather than setInterval to stay synchronized with the browser's paint cycle.

Detection

  • ID: performance-deep-dive.regression-prevention.animation-frame-budget

  • Severity: info

  • What to look for: Count all animation implementations. Enumerate which use requestAnimationFrame or CSS transforms vs. setInterval or property-based animations. Examine animation and scroll handling code. Check for use of requestAnimationFrame. Look for CSS transforms and transitions vs. property-based animations (JS-driven).

  • Pass criteria: Animations use requestAnimationFrame or CSS transforms (GPU-accelerated). Frame rate stays at 60fps (16ms per frame). No jank during scrolling or animations. At least 90% of animations should use GPU-accelerated techniques (CSS transforms or requestAnimationFrame).

  • Fail criteria: Animations use setInterval or property-based JS animations that block main thread. Frame rate drops below 60fps.

  • Skip (N/A) when: The application has no animations or scroll interactions.

  • Cross-reference: For paint profiling of animations, see paint-profiling-clean.

  • Detail on fail: "Scroll listeners change layout properties per frame — main thread blocked, frame rate drops to 30fps" or "Animations use setInterval instead of requestAnimationFrame"

  • Remediation: Use hardware-accelerated animations with CSS transforms or requestAnimationFrame.

    /* components/animated-card.module.css — GPU-accelerated */
    .card { transition: transform 0.3s ease; }
    .card:hover { transform: translateY(-4px); }
    

External references

Taxons

History