Troubleshooting guide · performance · Published 2026-08-16 · 3 min read
Debug CLS in the trace
Debug CLS in Chrome DevTools: enable the Layout Shifts panel, run a trace, and map shift events back to the element, ad slot, or font that moved it.
- ·Capture the trace
- ·Read the record
- ·Fix the source
The tool: the Layout Shifts panel in a Performance trace
Chrome DevTools makes layout shift debugging concrete. When you record a performance trace, the Layout Shifts checkbox in the experience row collects every Layout Shift record, and clicking one in the summary highlights the element that moved it in the DOM, with a red/yellow outline overlay in the frame.
The workflow is always the same order:
- Open DevTools > Performance.
- Check the
Layout Shiftsbox in the capture settings. - Record, load the page (a hard reload with a slow connection is ideal because late-arriving images and third parties are what trigger shifts).
- Stop and look in the summary under
Layout Shifts: each record is one shift with its score and source.
The trace records the shift even when it is tiny, which is what lets you see the difference between a font swap that moves text a few pixels and a hero that jumps by half the viewport.
Read the record
Each shift record shows the moved element, the affected nodes in the trace, and under Details the shift score the metric will compute. Compare across a few reloads: a consistent element (the same hero, sidebar ad, or cookie banner container) appears in nearly every trace, while a one-off food embed may appear once. The consistent one is the CLS you are shipping, not the noise.
The three sources in the debugger order given by the CLS fix guide:
| Source | What the trace shows | The fix |
|---|---|---|
| Missing image dimensions | An img/aspect-ratio node appearing late, shifting text below it | Reserve width/height in HTML |
| Font swap | A text node re-lays out when the webfont arrives | font-display: swap or preload |
| Late injected widgets | An ad/chat container inserted after layout | Reserve the slot with min-height |
Turn the trace into a fix
- Read the records by element: a hero shows
Layout Shiftonimg#hero; an ad showsdiv.ad-slot. - Re-run with network throttling off to see whether the shift also fires when assets are cached; if it disappears on a warm reload, the shift is asset-timing-driven (late image or font), not structural.
- Apply the reserve fix and re-capture: the shift should disappear from the trace records, because the layout box exists before the asset arrives and the metric no longer counts it.
Diagnosing the special classes
- Hero images with
fetchpriority="high": these shift because the browser already reserved nothing; thewidth/heightfix still applies even with a preload. - CSS variables and style recalcs: a shift that follows a
stylechange on a parent (a sidebardisplayflip) shows in the trace as a large area moving; check theLayout.changespanel as well. - Late third-party script injected layout: the trace shows the script frame creating the widget then shifting; the fix moves the injection off the main flow entirely.
The trace is the ground truth. The CLS optimisation article explains the mechanism behind each fix; the layout shift forms article covers the specific interactive-move class; and the audit procedure article places CLS into the field-vs-lab loop so a DevTools trace is not the only proof you keep.