Fixing CLS and INP: stopping layout shifts and sluggish clicks
· 7 min read
You go to tap "Add to cart", an ad banner loads above it, the page lurches down and you tap "Remove" instead. Or you tap the menu icon and nothing happens for a full second, so you tap again and it opens and closes. The first is a layout shift problem, measured by Cumulative Layout Shift. The second is a responsiveness problem, measured by Interaction to Next Paint. Both frustrate visitors in ways a load-time number never shows. This guide explains how to fix CLS and INP issues, with separate diagnosis and remedies for each.
The "good" thresholds are a CLS of 0.1 or less and an INP of 200 milliseconds or less, both at the 75th percentile of real visits.
Understanding what CLS actually counts
CLS scores unexpected movement of visible content. A shift that happens within half a second of a user’s tap or key press is treated as expected and excluded, which is why opening an accordion on click does not count against you. Movement nobody asked for does count: late images, injected banners, cookie bars that push content down, and fonts that change size when they load.
The score considers how much of the screen moved and how far. Because it is measured across the life of the page, shifts that happen while someone scrolls far down still add up.
Finding the elements that shift
- PageSpeed Insights: the "Avoid large layout shifts" diagnostic lists the elements that moved most during the lab run.
- Chrome DevTools: in the Rendering panel, enable "Layout Shift Regions" to flash a highlight wherever content moves while you use the page.
- Performance panel: record a load and scroll; layout shifts appear as markers you can click to see the affected nodes.
- Slow it down: throttle the network to a slow profile so late-loading elements are easier to catch.
Lab tools only see shifts during load. If field data shows poor CLS but the lab looks fine, test by scrolling, opening pop-ups and waiting on the page.
Fixes for layout shifts
Give every image and video dimensions
Add width and height attributes to img and video elements. Modern browsers use them to calculate the aspect ratio and reserve the right amount of space before the file arrives, even when CSS makes the image responsive. For embeds like YouTube iframes, the CSS aspect-ratio property does the same job.
Reserve space for ads and dynamic slots
Ad slots, "related products" carousels and review widgets often start at zero height and expand. Set a min-height on their container that matches the most common size. An empty gap for a moment is far better than the page jumping.
Stop pushing content down from the top
Announcement bars, cookie consent notices and "download our app" banners inserted above existing content shift everything below. Either include them in the initial HTML with space already reserved, or overlay them at the bottom of the screen with fixed positioning so they cover rather than displace content.
Tame web font swaps
With font-display: swap, text first appears in a fallback font and then re-renders in the web font. If the two fonts have different widths, lines rewrap and the layout moves. Options include preloading the main font file so it arrives sooner, choosing a fallback with similar proportions, and using the size-adjust and related descriptors in @font-face to match fallback metrics to the web font.
Animate with transform
Animations that change top, left, height or margin trigger layout changes. Use CSS transform for movement and scaling, which does not shift surrounding elements.
Understanding what INP measures
INP looks at the clicks, taps and key presses during a visit and reports close to the slowest one. The time runs from the user’s input until the browser paints the next frame showing a response. It includes three stages:
- Input delay: the browser is busy with other JavaScript and cannot start handling the event.
- Processing time: your event handler code runs.
- Presentation delay: the browser recalculates styles and layout and paints the result.
The root cause is nearly always the main thread being blocked. Browsers run JavaScript, layout and painting on a single main thread, so one heavy task makes everything wait.
Finding slow interactions
INP needs real interactions, so a simple page-load test will not reveal it. In Chrome DevTools, open the Performance panel, enable CPU throttling to mimic a slower phone, start recording, and then use the page: open menus, change filters, type into search, add items to the cart. Look for red-flagged long tasks, meaning anything over 50 milliseconds, around each interaction. The flame chart below shows which scripts were running.
Field data tells you which pages have poor INP; lab recording tells you which interaction and which script is responsible.
Fixes for sluggish interactions
Break up long tasks
If a click handler filters 500 products, updates the count, re-renders the grid and sends an analytics event all at once, the screen cannot update until everything finishes. Do the visible update first, then yield back to the browser before doing the rest. Developers commonly use setTimeout or, in supporting browsers, scheduler.yield() to split work into smaller chunks.
Give instant visual feedback
Show a pressed state, spinner or "Adding…" label immediately, and let the slower work continue afterwards. The next paint happens sooner, which is exactly what INP measures.
Reduce JavaScript competing for the main thread
Chat widgets, heatmap tools, multiple analytics tags and social embeds all run code on the same thread as your menus. Remove tags nobody uses, and delay non-essential ones until after the page has settled.
Debounce busy inputs
Search-as-you-type fields that run a full search on every keystroke can lock up slower phones. Wait until the user pauses briefly before running the search.
Keep the DOM reasonably small
Pages with thousands of elements take longer to restyle and repaint after each interaction. Paginate long lists, and avoid hidden copies of the same menu for desktop and mobile where one would do.
A combined checklist before your next release
- All images, videos and iframes have dimensions or an aspect ratio
- Ad and widget containers have reserved minimum heights
- No banners inserted above existing content after load
- Main web font preloaded, with a closely matched fallback
- No long tasks over 50 ms on menu, filter or add-to-cart clicks under CPU throttling
- Buttons show immediate feedback when pressed
- Unused third-party scripts removed
Online stores tend to have the heaviest filters and cart interactions, so they benefit most from this work. Our online store development team builds these interactions with responsiveness in mind.
Frequently asked questions
What replaced FID in Core Web Vitals?
Interaction to Next Paint replaced First Input Delay in March 2024. FID only measured the delay before the first interaction was handled, while INP covers the full response time of interactions throughout the visit.
Why is my CLS good in the lab but poor in field data?
Lab tests only measure the initial load without scrolling or clicking. Real visitors trigger late-loading ads, pop-ups and infinite scroll, which cause shifts the lab never sees.
Do cookie consent banners hurt CLS?
They can if they push page content down. A banner overlaid at the bottom of the viewport with fixed positioning avoids shifting other elements.
Can a WordPress site have good INP?
Yes. INP depends on how much JavaScript runs, not on the platform itself. Limiting plugins that add front-end scripts and removing unused widgets usually makes the biggest difference.
Thinking about a website?
See what a package covers and what it costs, or ask us about your own project.