Skip to content
ThemesIonic — home
Troubleshooting

How to Fix Cumulative Layout Shift in WordPress

Layout shift comes from content that arrives after the page has started rendering. Reserve space for images, ads, embeds and fonts, and the metric fixes itself.

4 min read intermediate

The whole fix in one sentence: anything that arrives late must have its space reserved in advance. Images, ads, embeds, banners and fonts are the five sources, roughly in that order of frequency.

Measure it properly

Two different numbers:

  • Lab data from a page speed tool — repeatable, useful for before-and-after comparison, but a single viewport on a fast connection.
  • Field data in Search Console's Core Web Vitals report — real visitors on real devices, and the number that counts.

Find what is actually moving using the Performance panel in DevTools: record a page load, then look at the Layout Shift entries. Each one names the element that moved. That beats guessing every time.

Cause 1: images without dimensions

The most common cause by a distance. An <img> with no width and height occupies zero space until the file arrives, then pushes everything below it down.

<!-- Reserves the correct box before the file loads. -->
<img src="photo.webp" width="1600" height="900" alt="…">

WordPress adds these automatically for images inserted through the editor. They go missing when a theme template outputs raw <img> tags, when a page builder writes its own markup, or when a plugin rewrites images for lazy loading.

Check the page source of the offending page. If the attributes are absent, the fix belongs in the template or the plugin producing them — the broader image work is in how to optimise images in WordPress.

For CSS-driven boxes, aspect-ratio reserves space without fixed pixel values:

.card-image {
    aspect-ratio: 16 / 9;
    width: 100%;
    height: auto;
}

Cause 2: ads and embeds

An ad slot or an embedded video that sizes itself after loading shifts everything below it.

Reserve the space with a container sized to the expected dimensions:

.ad-slot {
    min-height: 250px;  /* the height of the ad you actually serve */
}
.video-embed {
    aspect-ratio: 16 / 9;
}

If ad sizes vary, reserve the largest common size rather than the smallest — a little whitespace is much cheaper than a shift.

Cause 3: web fonts

A font that loads after render causes text to reflow when it swaps in — a "flash of unstyled text" that counts as layout shift when metrics differ.

  • Use font-display: swap so text is readable immediately, and choose a fallback with similar metrics so the swap moves as little as possible.
  • Preload the one or two font files used above the fold.
  • Self-host fonts where licensing allows, removing a third-party connection from the critical path.
  • Cut the number of weights. Three weights of one family is usually plenty — the selection reasoning is in how to choose fonts for a website.

Cause 4: banners and notices injected at the top

Cookie notices, promotional bars and "we use cookies" panels that insert themselves into the flow push the entire page down after it has rendered.

Fix by taking them out of the flow:

.consent-banner {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 999;
}

A fixed overlay covers content rather than displacing it, and contributes nothing to CLS. Most consent plugins offer this as a display option — see cookie consent plugins.

Cause 5: lazy loading above the fold

Lazy-loading the hero image delays it, and when it finally arrives it pushes content around. Load the largest above-the-fold image eagerly with high priority, and lazy-load only what is below the fold.

Aggressive JavaScript lazy loaders applied to everything are a frequent cause of both poor CLS and poor LCP. If a performance plugin offers "lazy load all images", exclude the hero.

Cause 6: content inserted by scripts

Related-post widgets, review stars, personalisation and A/B testing tools that write into the page after load all shift it.

  • Render server-side where possible.
  • Reserve space for the injected element.
  • Load such scripts after the main content, and question whether they earn their place at all.

A note on animations

Animating top, left, width or height triggers layout and can register as shift. Animate transform and opacity instead — they are composited and do not move surrounding content.

Verify

Re-record a page load in the Performance panel and confirm the shift entries are gone. Then wait for the field data to catch up — Search Console reports on a rolling window, so improvements take weeks to show even when the fix is immediate.

If the page is also slow rather than just unstable, the two problems are usually related and the wider method is in how to speed up a WordPress site.

Frequently asked

0.1 or below in field data. Lab scores are useful for comparison, but the field measurement from real visitors is what search engines use.
Lab tests use a fixed viewport and fast connection. Real visitors have slower networks and varied screens, where late-loading elements shift more.
Yes, when they push content down after rendering. A fixed-position overlay that sits above the page rather than displacing it avoids the problem entirely.

Related guides