Frontend Labs
⋯

22. Compositing and the GPU: layers, rasterization, the 16.6ms frame budget, jank

At 60Hz, the browser has 16.6ms to go from "something changed" to "a new frame is on screen" — miss that budget and a frame is dropped, which the human eye perceives as jank (stutter). The budget is shared:

16.6ms frame budget, roughly:
  JavaScript (event handlers, your animation logic)   |
  Style recalculation (CSSOM re-match)                 |  all on the MAIN thread
  Layout (if triggered)                                |
  Paint (if triggered)                                 |
  Composite                                             — can run on a SEPARATE compositor
                                                            thread, independent of main-thread JS

Elements get promoted to their own compositor layer (visible in DevTools via the "Layers" panel) when they have a transform/opacity animation, will-change, <video>, or a few other triggers — once promoted, the GPU can move/fade that layer independently, without asking the main thread to redo any work, which is exactly why compositor-only animations stay smooth even while the main thread is busy running your JS.

/* Hint the browser to promote this element to its own layer BEFORE the
   animation starts, avoiding an expensive layer-promotion mid-animation. */
.will-animate {
  will-change: transform;
}

Overusing will-change is a real anti-pattern: every promoted layer costs GPU memory, and a page with hundreds of unnecessary layers can be slower than one with none — apply it narrowly, right before an animation starts, and remove it after.

Generated from real-life-JS-guide.md · 8 Oct 2026 16:36