
Frame Budget Basics
PerformanceA frame budget is the maximum amount of time the browser has to produce a single visual frame. At 60 frames per second - the standard target for smooth animation on the web - each frame must complete in 16.67 milliseconds. Miss that window, and the frame drops. Drop enough frames, and the user sees stutter.
This note covers what happens inside that 16.67-millisecond window, where time gets spent, and how to make animation choices that stay within the budget. The principles connect directly to the Performance section’s treatment of render costs and to the motion design decisions discussed in Motion Language.
What fills the frame
Each frame involves several stages, and the browser must complete all of them within the budget.
JavaScript execution comes first. Any script that runs in response to scroll events, intersection observers, animation frame callbacks, or timers runs before the browser can begin visual work. If JavaScript takes 12 milliseconds, only 4.67 milliseconds remain for everything else.
Style calculation comes next. The browser determines which CSS rules apply to which elements. On a page with a large stylesheet and many elements, this can take several milliseconds.
Layout follows. The browser calculates the position and size of every element whose geometry may have changed. This is the most expensive stage for pages with complex layouts. A single layout change can cascade through hundreds of elements if they share layout containers.
Paint converts the calculated layout into actual pixel data. The browser draws each visible element into bitmaps. Larger areas and more complex visual treatments - shadows, gradients, filters - cost more paint time.
Compositing is the final stage. The browser assembles the painted layers into the final image that appears on screen. This stage is the cheapest and is handled by the GPU.
Where budget overruns happen
The most common budget overrun is layout thrashing - JavaScript code that reads layout properties (like offsetWidth or getBoundingClientRect) and then writes layout-affecting properties (like width or margin), forcing the browser to recalculate layout multiple times within a single frame.
The fix is to batch reads and writes. Read all the values you need first, then write all the changes. This allows the browser to perform a single layout calculation rather than one per read-write cycle.
The second most common overrun is animating expensive properties. Width, height, margin, padding, top, left, border-width, and font-size all trigger layout recalculation. On a page with many elements, animating any of these properties can blow the frame budget by forcing full layout recalculation on every frame.
The solution is to animate only transform and opacity. These properties are handled by the compositor thread and do not trigger layout or paint. A visual effect that moves an element can use translateX or translateY instead of changing its left or top position. A visual effect that resizes an element visually can use scale instead of changing its width or height.
Measuring actual performance
The browser’s developer tools provide precise frame-by-frame performance analysis. The Performance panel in Chrome DevTools records every stage of the rendering pipeline and shows where time is being spent.
The critical metric is not average frame time but worst-case frame time. A page that maintains 60fps on average but drops to 15fps during transitions has a stutter problem. The human eye is more sensitive to variation than to consistent low frame rates. A steady 30fps feels smoother than an inconsistent frame rate that averages 45fps.
Use the performance monitor on actual target devices, not just development hardware. A fast desktop machine can hide performance problems that become visible on phones. The rendering pipeline on mobile GPUs is different - smaller caches, lower clock speeds, shared memory with the CPU - and problems that do not exist on desktop can be severe on mobile.
Practical frame budget allocation
A useful rule of thumb for interactive pages: allocate no more than 4 milliseconds to JavaScript, 2 milliseconds to style calculation, and 2 milliseconds to layout. That leaves roughly 8 milliseconds for paint and compositing, with some margin for browser overhead.
This allocation means keeping animation-related JavaScript minimal. A scroll handler that calculates one or two transform values is fine. A scroll handler that iterates over fifty elements and calculates complex interpolations is not.
It also means keeping the DOM relatively simple during animated sections. A page with a thousand visible elements has a fundamentally higher style calculation and layout cost than a page with two hundred visible elements. If a section needs complex animation, the section itself should have a streamlined element count.
Connection to motion design
Frame budget awareness is not just a performance concern. It is a design constraint that shapes creative decisions. A motion design that calls for twenty simultaneous animations is technically achievable on fast hardware but will fail on the devices that most of the audience actually uses.
Designing within the frame budget means choosing fewer, more impactful animations rather than many subtle ones. It means preferring compositor-only properties. It means testing on constrained devices early and often, not as a final validation step but as an ongoing design input.
The Journal entry on keeping immersive pages light explores how these constraints influence broader production decisions.