How to Fix Cumulative Layout Shift (CLS) on WordPress
Content jumps as the page loads and Search Console reports a CLS issue. Find the element that moves and why, then reserve space for images, embeds, ads, fonts and banners.
Search Console or PageSpeed Insights says your LCP is too slow. Find the LCP element, see which of its four parts is slow, and fix the hero image, server time or render blocking.
Search Console’s Core Web Vitals report has flagged a group of pages with “LCP issue: longer than 2.5s (mobile)”, or PageSpeed Insights shows Largest Contentful Paint in orange or red. Your site may feel fine on your office Wi-Fi. On a real visitor’s phone, the main content is taking too long to appear.
This guide explains what LCP measures, how to find exactly which element is slow and why, and the fixes that work on WordPress sites built with themes and page builders. It is for site owners who want to understand the report and the developers or designers who will make the changes. Broader speed problems are covered in slow websites: images, fonts and animations and high TTFB; responsiveness after load is in poor INP.
Largest Contentful Paint is the time from when the visitor starts loading the page until the largest image or text block visible in the first screen has been drawn. Elements that can count include <img> images, the poster image of a <video>, an image loaded as a CSS background-image, and block-level text such as a heading or paragraph.
Google’s thresholds, from web.dev, are measured at the 75th percentile of page loads, separately for mobile and desktop:
| LCP | Rating |
|---|---|
| 2.5 seconds or less | Good |
| Over 2.5 and up to 4 seconds | Needs improvement |
| Over 4 seconds | Poor |
The 75th percentile means three out of four visits must be at or under 2.5 seconds for the page to pass. A fast experience on your laptop does not count for much if most of your visitors arrive on phones over mobile data.
web.dev and Chrome break LCP into four subparts that add up to the total. Knowing which part is large tells you which fix to apply.
| Subpart | What it covers | Typical WordPress causes |
|---|---|---|
| Time to First Byte (TTFB) | From the start of navigation until the first byte of HTML arrives. | No page cache, slow hosting, heavy plugins running on every request, redirects, a distant server with no CDN. |
| Resource load delay | From TTFB until the browser starts downloading the LCP image. Zero for text. | The hero image is lazy-loaded, set as a CSS background, inserted by JavaScript (sliders), or discovered late behind other files. |
| Resource load duration | How long the LCP image takes to download. | An oversized image (a 4000 pixel photo shown at 400 pixels), old formats, no CDN. |
| Element render delay | From the image finishing (or TTFB, for text) until the element is actually painted. | Render-blocking CSS and JavaScript, web fonts hiding text, builder entrance animations that keep content invisible until a script runs. |
web.dev’s own analysis of real-world data notes that the download itself is often not the biggest part; the delays before and after usually matter more. So “compress the image” is not always the answer.
Search Console and the top of PageSpeed Insights show field data from the Chrome User Experience Report: real Chrome users over the previous 28 days. The lower part of PageSpeed Insights and Lighthouse show lab data: one simulated load on a throttled phone. Field data is what Google uses; lab data is what you can test changes with today. They will not match exactly. Because field data is a 28-day rolling window, a fix takes weeks to show fully in Search Console.
img with its file name, or an h1, and shows the subpart timings for the lab test.Note whether the LCP element is an image or text, and whether it is the same element on every page of the group. On mobile it is often different from desktop: a big heading may be the LCP element on a phone while a wide photo wins on desktop.
The biggest subpart decides your next step: TTFB goes to Step 3, resource load delay to Step 4, load duration to Step 5, and render delay to Step 6.
You can also check the HTML for the hero image without opening DevTools. On your computer:
curl -sL https://example.com/ | grep -oE '<img[^>]*>' | head -n 5
curl -sL downloads the page following redirects, grep -oE prints each <img> tag on its own line, and head -n 5 keeps the first five, which are the ones nearest the top of the page. Good: the hero image has fetchpriority="high" and no loading="lazy". Bad: the hero has loading="lazy", a data-src or data-lazy-src attribute instead of src (a lazy-load script will swap it in later), or it does not appear at all because it is a CSS background or injected by a slider script.
If the HTML itself takes more than about 800 milliseconds to start arriving (web.dev’s rough guide for a good TTFB), nothing else can be fast. Common fixes, in order:
http://example.com that redirects to https://www.example.com/ adds a full round trip to every visit. See one-hop redirects.Quick measurement from your computer:
curl -s -o /dev/null -w "ttfb: %{time_starttransfer}s total: %{time_total}s\n" https://example.com/
-o /dev/null throws away the page (use NUL on Windows), and -w prints the time until the first byte and the total time, in seconds. Run it three times; the first may be a cache miss. Numbers consistently above about 0.8 seconds for a cached page point to the server.
Lazy loading is good for images further down the page and bad for the one at the top. A lazy-loaded hero is not requested until the browser has laid out the page and worked out it is visible. Lighthouse flags this as “Largest Contentful Paint image was lazily loaded”.
WordPress core already tries to skip lazy loading for the first content images and, since WordPress 6.3, adds fetchpriority="high" to the image it judges most likely to be the LCP element. Themes, page builders and optimization plugins often override this by lazy-loading everything. Look in these places:
src to data-src.The fetchpriority="high" attribute tells the browser to fetch this image ahead of other images. If your hero is a normal image element and WordPress did not add it, add it through your builder’s attribute field or the theme template:
<img src="https://example.com/wp-content/uploads/hero-1200.jpg"
srcset="https://example.com/wp-content/uploads/hero-800.jpg 800w,
https://example.com/wp-content/uploads/hero-1200.jpg 1200w"
sizes="100vw" width="1200" height="600"
fetchpriority="high" alt="Describe the image">
Use it on one image per page, the real LCP image. Marking everything high priority means nothing is.
The browser’s preload scanner only finds images that appear as <img> elements in the HTML. Three common hero patterns hide the image:
When you cannot change the markup, a preload link in the <head> makes the browser start early. Many optimization plugins have a “preload LCP image” option that generates this; otherwise:
<link rel="preload" as="image" fetchpriority="high"
href="https://example.com/wp-content/uploads/hero-1200.jpg"
imagesrcset="https://example.com/wp-content/uploads/hero-800.jpg 800w, https://example.com/wp-content/uploads/hero-1200.jpg 1200w"
imagesizes="100vw">
Preload only the image that really is the LCP element on that template, and only on that template; a sitewide preload of a home page hero wastes bandwidth everywhere else. If the image is on a different domain (a CDN), add a preconnect to that domain as well.
srcset so the browser can choose a smaller version; WordPress generates one for images inserted from the Media Library, but builders and custom HTML sometimes output the full size only. See thumbnails and image sizes.Check what the browser actually downloaded in DevTools Network, filtered to Img: the size column shows bytes transferred, and hovering over the image in Elements shows its rendered size compared with its intrinsic size.
The image or text is ready but the browser cannot or does not paint it yet.
Builder animations such as “fade in up” on the hero section start the element invisible and reveal it with JavaScript. The LCP element cannot be painted until the animation runs, and if a speed plugin delays JavaScript until user interaction, it may not run until the visitor moves the mouse. Remove entrance animations from anything in the first screen. This is one of the most common LCP problems on builder sites and one of the easiest to fix.
Stylesheets in the <head> and scripts without defer or async block rendering. Reduce them by removing unused plugins, using your optimization plugin’s critical CSS or “remove unused CSS” feature carefully, and deferring non-essential scripts. Test thoroughly afterward, because aggressive settings break menus and forms; broken after Delay JS explains how to find the script that needs an exclusion.
If the LCP element is a heading, a web font that has not loaded can hide the text. Use font-display: swap (or optional), self-host fonts instead of loading them from a third party, preload the one font file used for the heading, and use fewer font weights. See fonts showing as Times New Roman for how fonts are loaded and fixing CLS for keeping the font swap from shifting the layout.
On a phone, a consent banner with a paragraph of text can itself become the LCP element, and its script may load late from a third-party domain. Shorten the text and load the banner script early. See cookie banner problems.
If lab results are good but field data stays poor, your real visitors may be on slower devices or networks than your test settings, or the problem may be on pages or states you did not test (logged-in users, visitors arriving from ads with tracking parameters that skip the cache, or another country far from your server).

If TTFB is the biggest subpart even with page caching turned on, the server is the bottleneck. Send your host:
curl command above;The performance metrics and headers cheat sheet lists every metric and cache header in one place.
Did this fix it?
Still stuck? Start again from what you can see in the Emergency Room.
Still stuck?
Print a free one-page checklist to keep, or open the Emergency Room if the symptom does not match.
Get the free checklistsKeep reading
Search the field manual
Or jump straight to a symptom
Press / to search from any page, Esc to close