CSSLayer Promotion & Compositor

Layer Promotion & Compositor

To understand why some CSS animations feel buttery smooth while others stutter, it helps to know what the browser actually does between you writing a style change and pixels appearing on screen. That path runs through three broad stages: layout, paint, and composite — and which stage your change touches determines how expensive it is.

Layout → Paint → Composite

Stage

What happens

Triggered by

Layout

The browser recalculates the size and position of every affected element on the page.

width, height, margin, position offsets, font-size, and other geometry-affecting properties.

Paint

The browser fills in pixels for each box — text, colors, shadows, borders — onto one or more layers.

color, background, box-shadow, border-radius, and anything layout did not already invalidate.

Composite

The GPU combines all painted layers into the final image shown on screen, applying any transforms/opacity along the way.

transform, opacity — and any property change on an already-promoted layer.

A style change that only affects the composite stage is dramatically cheaper than one that forces layout, because layout and paint often have to redo work across large parts of the page, while composite can run independently on the GPU. For the full story on why layout and paint are expensive, see Repaints & Reflows.
What Promotes an Element to Its Own Layer
Certain CSS triggers cause the browser to give an element its own compositor layer — essentially a separate texture the GPU can move, fade, or transform on its own, without asking the rest of the page to repaint. The most common triggers are the transform and opacity properties, and the will-change property (see will-change), which can hint at promotion ahead of time.

CSS
/* These changes stay on the compositor — cheap, GPU-driven */
.card {
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.card:hover {
  transform: translateY(-4px) scale(1.02);
  opacity: 0.95;
}

/* Hinting the browser to promote ahead of an upcoming animation */
.card {
  will-change: transform, opacity;
}

/* Contrast: animating layout-affecting properties forces
   layout + paint on every frame, on the main thread */
.card-slow {
  transition: width 0.2s ease, margin-top 0.2s ease;
}
.card-slow:hover {
  width: 220px;      /* triggers layout every frame */
  margin-top: -4px;  /* triggers layout every frame */
}

Once an element is on its own layer, animating transform or opacity on it only requires the GPU to recompute how that one texture is positioned or blended — the rest of the page's layers are untouched. That is the entire reason transform/opacity animations run smoothly even on lower-powered devices, while animating width, top, or margin can visibly drop frames: every frame of the animation re-triggers layout and paint across the affected region instead of a cheap GPU composite step.

Layer Explosion
Too many layers can hurt performance
Compositor layers are not free. Each one consumes GPU memory, and the browser has to manage and merge every layer on every frame. Overusing will-change, or applying transform/opacity-triggering styles to large numbers of elements, can create dozens or hundreds of layers — a problem often called "layer explosion." On memory-constrained devices this can slow a page down more than the repaints it was meant to avoid, and can even crash the tab.

CSS
/* Risky: promotes every card on the page permanently,
   whether or not it is animating right now */
.card {
  will-change: transform;
}

/* Better: only hint promotion right before the animation starts,
   and remove the hint once it finishes (often via JS toggling a class) */
.card.is-animating {
  will-change: transform;
}
Use layer promotion judiciously
Reach for transform/opacity animations and will-change specifically for elements that are actively animating and where you have measured jank — not as a blanket "performance" class applied to everything. A handful of well-chosen compositor layers will outperform a page full of them.
Note
Browser DevTools can visualize compositor layers directly (e.g. Chrome's "Layers" panel), letting you confirm which elements were actually promoted and spot unexpected layer explosion before it becomes a real problem.