skip to content

A product manager reports that a list animation "feels janky" on real phones, though it looks fine on your laptop. What number would you use to describe animation smoothness, and how would you measure it?

level: seniorimportance: should knowfreq 42%

answer

  1. averages hide the frames people notice
  2. share of frames not presented
  3. plus the worst single frame
  4. the laptop is not the user's device
  5. end with a budget you can re-run

basics

~20 s

Report the percentage of frames dropped during the animation, plus the duration of the worst frame — not average frames per second. Measure it by recording a performance trace on a slow reference device or with CPU throttling while performing the interaction, and read the frames the browser could not present on time.

solid answer

~50 s

Average fps is the wrong number: an animation that hits 60 fps for 200 frames and stalls for four still averages near 60 and still looks broken. Describe smoothness with the **share of frames the browser failed to present during the animation window** and the **longest single frame**, because those are what the user actually perceives. To get them, reproduce the animation while recording a performance trace and inspect the frames the browser marks as dropped or partially presented; Chrome's Rendering drawer also has a live frame-rendering-stats overlay for a quick read. Crucially, measure on hardware resembling your users' — a mid-tier Android phone, or your laptop with CPU throttling applied — because a developer machine can be several times faster and will simply not reproduce the problem. Then turn it into a budget: "this interaction drops no more than 2% of frames, and no frame exceeds 32 ms, on the reference device", which gives you a pass/fail you can re-run after a fix.

go deeper

for a junior

Know that smoothness is judged by frames the browser failed to deliver, not by an average frame rate, and that a fast development machine can hide a problem that real phones show.

for a middle

Explain how you would get the number: record the specific interaction with CPU throttling or on a real device, then read which frames were dropped and how long the worst one took, rather than eyeballing the animation.

for a senior

Show the full loop — reproduce on representative hardware, report dropped-frame share alongside the worst frame, use where the drops cluster to separate setup cost from per-frame cost, and re-measure identically to prove the fix.

for a principal

Own the standard: which device tier smoothness is defined against, what dropped-frame ceiling an interaction must meet, and how that ceiling is defended as features accumulate motion — plus knowing when lab numbers must defer to field data.

## Why "janky" needs a number "Feels janky" is a real report and a useless bug ticket. It cannot be assigned, cannot be verified as fixed, and cannot be defended in a review. The first job is to convert the complaint into a measurement that (a) reproduces, (b) matches what the user perceived, and (c) has a threshold you can pass or fail. ## Why average fps is the wrong metric Frame rate averaged over an animation hides exactly the events people notice. Consider a 3-second animation at 60 Hz: about 180 frames. If 176 land on time and four frames each take 100 ms, the arithmetic still reports something in the high 50s — while the user sees the animation freeze for a quarter of a second in the middle. Smoothness is a property of the worst frames, not the mean. The same reasoning is why a frames-per-second counter drawn on the page is a weak tool. Besides costing work of its own, it typically shows a rolling average, which is the number that hides the problem. And counting your own callbacks is not the same as counting frames the display actually presented — an animation can be delivering frames without your loop running, and your loop can run without a frame reaching the screen. ## The numbers worth reporting Two, together: 1. **Dropped-frame percentage over the interaction window.** Of the frames the display expected during the animation, what share did the browser fail to present? This is the metric browsers themselves use for smoothness, and it is scale-independent — it means the same thing at 60 Hz and 120 Hz, which matters when your users are on both. 2. **The longest frame.** One 250 ms frame is a different defect from fifty 20 ms frames, with a different cause and a different fix. The maximum, or a high percentile of frame duration, keeps that distinction visible. If you want a third, add *when* in the animation the drops cluster: at the start (setup cost — measurement, style recalculation, new elements entering), spread evenly (per-frame work simply exceeds the budget), or in one lump partway through (something unrelated stole the thread). ## Measuring it honestly **Reproduce on representative hardware.** This is the whole reason the laptop showed nothing. A developer machine can be several times faster than a mid-range phone, so the same per-frame work fits comfortably in one place and misses the deadline in the other. Either test on a real device from your target tier, or apply CPU throttling in DevTools so the profile approximates one. Pick a specific reference device and keep it fixed, otherwise numbers from different weeks are not comparable. **Record the interaction, not the page.** Start the recording, perform the exact gesture, stop. A trace of the whole page load buries the three seconds you care about. **Read the frames, then read the cause.** A performance recording shows each frame the browser produced and flags the ones it could not present in time. Chrome's Rendering drawer additionally offers a frame-rendering-stats overlay that shows a live dropped-frame reading while you interact, which is handy for a first pass before you commit to a full trace. **Confirm the fix by re-measuring the same way.** Same device, same throttling, same gesture, same window. "It feels better now" is how the ticket started. ## Turning it into a budget Once you have a number, write it down as an acceptance condition for the interaction: for example, *no more than 2% of frames dropped, and no frame over 32 ms, on the reference device*. Two things follow. First, the fix has a definition of done. Second, the number is a ceiling the next feature has to respect — motion tends to accumulate, and "one more animated element" is how a smooth interaction becomes a janky one over three sprints. Budget the *interaction*, not the page. A global "the app runs at 60 fps" is unmeasurable; "opening the filter drawer drops under 2% of frames on a Pixel-class device" is a test. ## Lab numbers versus what users get Even a well-run trace is a lab measurement: one device, one network, one state, one operator. It proves the animation *can* be smooth, not that it *is* smooth in production, where users have extensions, background tabs, thermal throttling and older hardware. Treat the trace as the diagnostic tool and the field data as the verdict — and expect the field distribution to be worse than your reference run, not better. ## What a strong answer sounds like Name the metric (dropped-frame share plus worst frame), reject the average, insist on representative hardware, describe how you would reproduce and record the specific interaction, and close the loop with a budget that makes the fix verifiable and protects it afterwards. Candidates who jump straight to a fix — "I'd use transforms" — are guessing; the interviewer is checking whether you measure before you change anything.

  • Why is a frames-per-second counter rendered on the page a poor way to judge smoothness?
    It usually shows a rolling average, which is the statistic that hides short stalls, and it costs work of its own inside the frames it is measuring. Counting your own callbacks also is not the same as counting frames the display presented. A recorded trace that flags frames the browser could not present answers the question directly.
  • The drops all cluster in the first 200 ms of the animation and then it runs clean. What does that pattern suggest?
    Setup cost rather than per-frame cost: work that happens once as the animation starts — measuring elements, inserting nodes, style and layout for newly visible content, decoding an image. Move that work before the animation begins, or start the motion only after the setup frame has settled, rather than trying to shave the steady-state frames.
  • How do you pick the reference device the budget is defined against?
    From your own analytics, not from intuition: look at the device and OS distribution of real sessions and pick something around the slower quartile of what people actually use. Then fix it. A budget measured against a moving target cannot be compared week to week, and a budget defined against a flagship phone passes for everyone except the users who are struggling.
  • Your trace on the reference device is clean, but field data still shows poor smoothness. What are you missing?
    A lab run is one device in one state with one operator. Real sessions bring extensions, background tabs, thermal throttling, low-battery modes, older hardware and different page states than the one you traced. Sample more of those conditions, and trust the field distribution over a single clean run when the two disagree.

saying these in an interview costs you the question

  • Reports average fps and calls a stuttering animation smooth
  • Measures only on a developer laptop with no throttling
  • Starts optimizing before reproducing the problem
  • Treats a page-level fps counter as evidence
  • Declares it fixed on feel rather than re-measuring the same way

context