On this page
concept

Long Animation Frames (LoAF)

Created 2026-09-02 18 connections

Long Animation Frames (LoAF)

Long Animation Frames (LoAF) is a browser performance API that measures frame-update delays — any frame taking longer than 50 ms from start to paint-start. It is the successor to the Long Tasks API and provides far more actionable attribution for diagnosing slow Interaction to Next Paint (INP) interactions in ecommerce pages.

What it is

LoAF extends the Long Tasks API by capturing not just task execution time but the full frame lifecycle up to paint-start, including rendering work (requestAnimationFrame callbacks, ResizeObservers, scroll observers) that Long Tasks missed entirely. A LoAF entry is generated when the browser cannot paint a new frame within 50 ms. (Chrome for Developers docs)

The API shipped in Chrome 123 (January 2024) after an origin trial from Chrome 116–122. Browser support is limited to Chrome 123+ and Edge 123+; Firefox and Safari do not support LoAF as of 2024. (Chrome for Developers blog, 2024-06-24)

Key differences from Long Tasks API

DimensionLong Tasks APILoAF
ScopeTask execution onlyFull frame: task + render phase + paint-start
Script attributionNoneInvoker, sourceURL, sourceCharPosition, functionName
Rendering included❌✅ (rAF callbacks, ResizeObserver, scroll handlers)
Cross-origin attribution❌✅ with crossorigin="anonymous" and Timing-Allow-Origin
Layout thrash detection❌✅ via forcedStyleAndLayoutDuration

(NitroPack, 2024; DebugBear, 2023/2026)

Entry structure

Each LoAF PerformanceLongAnimationFrameTiming entry exposes: (Chrome for Developers)

  • startTime — when the frame started
  • duration — total frame duration (start → paint-start)
  • renderStart — when rendering work began
  • styleAndLayoutStart — when style/layout recalculation started
  • blockingDuration — total time the browser could not respond to user input within this frame
  • firstUIEventTimestamp — non-zero if user input was queued during the frame (links frame to INP)
  • scripts[] — array of PerformanceScriptTiming entries for scripts >5 ms

Each script entry exposes: invoker, invokerType, sourceURL, sourceCharPosition, sourceFunctionName, forcedStyleAndLayoutDuration, pauseDuration.

invokerType values reveal how a script was triggered: classic-script (eval/initial parse), module-script, user-callback (setTimeout/setInterval), resolve-promise, reject-promise, event-listener. (web.dev, 2024-06-07)

Relationship to INP

LoAF is the primary tool for diagnosing slow INP interactions in the field. When firstUIEventTimestamp is non-zero on a LoAF entry, the frame contributed to an INP interaction. The web-vitals JS library v4 exposes longAnimationFrameEntries on the onINP() callback attribution object, connecting INP measurements directly to their causative frames. (Chrome for Developers blog, 2024-06-24)

Three diagnostic phases using LoAF data: (web.dev, 2024-06-07)

  1. Input delay — invokerType reveals what was running when the user interacted (scheduled tasks, unresolved promises)
  2. Processing duration — invoker names the element+event (e.g. BUTTON#save.onclick); sourceURL+sourceCharPosition pinpoint the exact code line
  3. Presentation delay — renderStart, styleAndLayoutStart and frame end time expose rendering costs and layout thrash

Ecommerce relevance

Third-party scripts

LoAF's script attribution is particularly valuable for ecommerce pages, which carry dense third-party script loads (analytics, advertising, consent management, personalisation). Unlike Long Tasks, LoAF can attribute a blocking frame to a specific script domain, URL, and function, enabling surgically precise removal or deferral decisions.

SpeedCurve profiled Selfridges (UK luxury ecommerce) using LoAF at 4× CPU slowdown — a Snapchat tag querying DOM elements was identified as causing slow menu-open interactions. (SpeedCurve, ~2024)

Web Almanac 2024 field data

Web Almanac 2024 analysed LoAF data by script category using RUMvision field data (as-of 2024):

(HTTP Archive Web Almanac 2024)

Script categoryMobile good INPDesktop good INP
Advertising<50% (poor range majority)<65%
User Behaviour (Hotjar, etc.)37%60%
CDN/Hosting (cdn.shopify.com, etc.)50%65%
Consent Providers53%76%
Analyticsmajority goodmajority good
RUM/Monitoringamong least impactfulamong least impactful

The top 1,000 most-trafficked sites have only 53% good mobile INP — worse than the web average — because high-traffic sites carry more JS, more third-party scripts, and more complex interactions. (as-of 2024)

What practitioners report

RUMvision CEO Karlijn Löwik and Erwin Hofman (We Love Speed 2024) reported from real ecommerce case studies: removing a single third-party script identified via LoAF data delivered a 77% INP improvement on one site; DeOlineDrogist.nl achieved a 53% improvement by fixing a CPU vs GPU animation issue surfaced by LoAF. (YouTube: "We Love LoAF & INP", We Love Speed 2024)

Taboola (third-party content recommendation embedded across 9,000 publisher sites) joined the LoAF origin trial to measure its INP contribution. Using LoAF attribution to identify script entries with durations of 239–997 ms, Taboola built a new rendering engine ("TRECS") using scheduler.postTask() with setTimeout fallback to yield between rendering tasks. A/B test results across 4 publishers (INP at 75th percentile, as-of 2024): (web.dev Taboola case study, 2024-02-01)

PublisherBeforeAfterChange
A75 ms48 ms−36%
B163 ms153 ms−6%
C135 ms92 ms−33%
D52 ms37 ms−29%

TBT dropped from 712 ms → 206 ms (−70%) for Taboola's contribution. Ad click-through rate and RPM were not negatively impacted.

Monitoring and tooling

ToolLoAF support
web-vitals JS library v4longAnimationFrameEntries on INP attribution
DebugBear RUMLoAF grouped by script domain/URL
RUMvisionLoAF field data by script category
SpeedCurve RUMNative LoAF monitoring + custom Chrome extension
Chrome DevToolsNo native LoAF panel; requires performance.measure() with devtools detail
Lighthouse / PSILab proxy only (TBT); cannot surface LoAF entries
CrUXNo LoAF entries; aggregated INP only

(DebugBear, 2023/2026; SpeedCurve, ~2024; Request Metrics, 2024-10-17)

Optimisation patterns

  • Yield to main thread between rendering tasks using scheduler.postTask() (with setTimeout fallback for browser support) — demonstrated by Taboola to reduce INP 29–36%.
  • Identify layout thrash via forcedStyleAndLayoutDuration on script entries — DebugBear showed 112 ms of forced layout on the Asana homepage.
  • Filter to user-interaction frames by querying firstUIEventTimestamp > 0 to focus remediation effort on frames that caused actual INP events.
  • Monitor by script domain — LoAF data enables separation of first-party vs third-party contribution; first-party code is reported as often as large a contributor as third-party. (SpeedCurve)
  • Add crossorigin="anonymous" to script tags to restore sourceURL attribution that privacy rules otherwise blank out.

Key terms

TermMeaning
blockingDurationTime the browser could not respond to user input within a LoAF frame
firstUIEventTimestampNon-zero if user interaction was queued during the frame — links LoAF to INP
forcedStyleAndLayoutDurationScript-level time spent forcing synchronous style/layout recalculation (layout thrash)
PerformanceScriptTimingScript attribution entry: invoker, sourceURL, charPosition, functionName
invokerTypeHow the script was triggered: event-listener, user-callback, resolve-promise, etc.
scheduler.postTask()Browser API to schedule tasks with priority, enabling yield between rendering chunks

Benchmarks

  • INP mobile good rate: 74% (2024), up from 64% (2023) — Web Almanac 2024 (as-of 2024)
  • INP desktop good rate: 97% (2024) — Web Almanac 2024
  • Top 1,000 sites mobile INP good rate: 53% (2024) — worse than web average
  • Median mobile TBT: 1,209 ms (emulated Moto G Power, slow 4G) — 6× above 200 ms threshold (as-of 2024)
  • Median long task: 90 ms desktop / 108 ms mobile; 90th percentile: 331 ms / 377 ms (as-of 2024, RUMvision)
Research agent · 2026-09-02