Counting Composited Layers in DevTools

A layer budget needs a number, and the number is surprisingly easy to get wrong: taken at rest it misses the peak, taken at the wrong pixel ratio it is off by an order of magnitude, and taken without reading the promotion reasons it says nothing about what to change. This guide covers getting a figure that supports a decision. It sits under GPU memory and layer budgets.

When to use this approach

  • Before adding an effect to a page that already has several. Establishing the current peak is the only way to know whether there is headroom.
  • When a page flickers or stutters on mobile but profiles cleanly. That combination is a memory problem, and the layer listing is where it is visible.
  • As a periodic audit. Layers accumulate through ordinary feature work, and nothing warns you.
  • After adding persistent chrome. A new sticky element or a backdrop filter changes the baseline for every page.
Three readings, three speeds Layer borders take seconds and show where layers are. Paint flashing takes seconds and shows whether anything is repainting. The Layers panel takes a minute and gives dimensions, memory and a promotion reason per layer. Start with the fast two and open the panel only when they are not enough. Layer borders — seconds shows where layers are, with no reading and no recording Paint flashing — seconds answers "is anything repainting", which is the more urgent question Layers panel — a minute dimensions, estimated memory and a promotion reason per layer A repainting element is a bigger problem than a badly-promoted one, and cheaper to find.

Implementation

1. Start with the fast readings

Enable layer borders and paint flashing from the rendering settings. Borders show you where the layers are, and flashing shows whether anything is repainting during a scroll. If something is repainting, stop here and fix that first — it is a larger problem than a badly-promoted layer and it is already identified.

2. Open the Layers panel and scroll

Read the peak, not the resting state Layer count over one scroll through an animated section. At rest before the section it is low. As elements enter and begin animating it rises. It falls again once they finish. The peak in the middle is the number the device has to accommodate, and a reading taken at either end misses it entirely. peak — this is the number before after scroll position Open the panel first, then scroll — a snapshot taken at rest reports a page that fits when it does not.

Layers are created and destroyed as elements begin and finish animating, so the count at rest is not the count that has to fit. Open the panel, then scroll through the section, and take the highest figure you see.

3. Set the pixel ratio before you read the memory

Device toolbar → a mobile preset → DPR 3

The memory column scales with the square of the pixel ratio. A figure read at 1x understates a modern phone by close to an order of magnitude, which is enough to turn a page that is comfortably over budget into one that looks fine.

4. Sort by memory, then read the reasons

Triaging a layer listing A listing sorted by memory. The largest entries are usually media and full-viewport chrome and are worth checking individually. Mid-sized entries with an animation reason are expected. Small entries with an overlap or legacy reason are the ones to remove, and there are usually many of them. Large — media and full-viewport chrome: check each one individually Medium, animation reason — expected; this is what the budget is for Small, overlap or legacy reason — remove; usually many of them Sorting by memory finds the big wins; sorting by reason finds the many small ones.

Sorting by memory finds the few large entries — usually media and full-viewport chrome — and each is worth justifying individually. Reading the reasons finds the many small ones, and the ones attributed to overlap or to a legacy transform hack are almost always removable.

5. Record the figure somewhere durable

A number in a commit message or a comment is a number that will be compared against next time. A number observed and not written down is an afternoon that has to be repeated.

Verification

Repeat the measurement after a change and confirm it moved in the direction you expected. Layer work is unusually satisfying in this respect: removing a standing will-change produces an immediately visible reduction, which makes it easy to tell whether a change was worth making.

Cross-check the total against a rough manual estimate — width times height times four times the pixel ratio squared, for the elements you know are promoted. If the panel’s total is far above your estimate, there are layers you have not accounted for, and those are the interesting ones.

Finally, confirm on a real device that the change produced the intended outcome. A reduction in a reported figure is a proxy; the absence of flickering on the phone that was flickering is the result.

Edge cases and gotchas

The panel reports estimates. These are the browser’s own figures rather than measurements from the driver. They are consistent enough to compare against each other and should not be treated as exact.

Layer count differs between page loads. Promotion depends on what is animating and what overlaps, both of which can vary with timing. Take the peak across a consistent scroll rather than a single snapshot.

Emulated device pixel ratio does not emulate memory. The figures scale correctly; the constraint does not appear. A page can report 200 MB in emulation and continue running perfectly on the development machine.

Off-screen sections may still hold layers. Unless content-visibility is skipping them, a promoted element outside the viewport can still be holding a texture. This is a common reason a long page’s peak is higher than any single screen would suggest.

Extensions add layers. Some browser extensions inject fixed-position elements. Measure in a clean profile.

Browser-specific notes

The Layers panel is a Chromium feature and there is no equivalent in Firefox. Safari’s Web Inspector has a layers sidebar showing composited elements and an estimated memory figure, which is less detailed but covers the same ground for triage.

Because the panel exists in only two of the three engines, the practical approach is to do the audit in Chromium — where unnecessary promotions are most visible — and rely on the fact that removing waste benefits every engine. The layer tree differs between engines; a stale will-change hint is waste in all of them.

Safari’s sidebar is worth using at least once for a page targeting iOS, because it reports against WebKit’s own promotion heuristics rather than Chromium’s, and the two can differ on which elements are promoted for overlap.

Frequently Asked Questions

Should paint flashing show nothing at all during a scroll?

For a compositor-driven section, yes. Some flashing is expected around content that is genuinely appearing — a lazily-loaded image arriving, a new section rendering — but the animated elements themselves should not flash. Flashing that follows the animation is the signature of a property outside the compositor-safe set.

Is the estimated memory figure per layer or cumulative?

Per layer. The panel does not total them, which is why sorting by memory and adding the top entries is a routine step rather than an optional one. A page with one 40 MB layer and thirty 0.2 MB layers has a very different problem from one with thirty 2 MB layers, and the totals alone would not tell you which.

What if the panel shows more layers than elements I animate?

That is the normal case, and it is the finding. Overlap promotion, fixed chrome, backdrop filters and legacy transform hacks all produce layers that no animation asked for. The gap between “elements I animate” and “layers the page has” is the size of the opportunity.

Does this need doing per page?

Per template, rather than per page. Pages sharing a layout share their chrome and most of their promotion behaviour, so measuring one instance of each template covers the site. Add a measurement for any page with unusual media weight, since that is where the large individual layers live.

How do I compare two measurements taken weeks apart?

Record the conditions along with the number: the page, the viewport size, the emulated pixel ratio, and whether the reading was the peak during a scroll or a resting snapshot. Without those, two figures are not comparable and a difference between them means nothing.

The habit that makes this sustainable is writing the measurement into the commit that changed the animation, rather than into a separate document. It is then attached to the code that produced it, and the next person comparing has both halves.

Is there a quick way to spot a page that is in trouble without any tooling?

Scroll the heaviest section on a mid-range phone with a few other applications open. If content blanks out momentarily, the budget is exceeded; if the animation stutters while buttons still respond, it is the compositor rather than the main thread. Neither observation identifies which layer is at fault, but both are decisive about whether there is a problem worth investigating — which is often all you need before deciding to spend an hour with the panel.


Up: GPU Memory & Layer Budgets