Why Is My LCP So High on Mobile: How to Fix It
Largest Contentful Paint is often comfortably under 2.5 seconds on desktop and well over it on mobile, sometimes for the same page on the same day. That gap is not a measuring error. Phones have slower processors, slower and less reliable networks, and often a different layout with a different main element. Google's Core Web Vitals assessment treats mobile and desktop separately, and for most sites mobile is where real visitors fail. This guide shows you how to find the exact element being measured on phones, work out whether it is waiting for the server, waiting to be discovered, downloading too slowly or waiting to be drawn, and make the specific HTML, image and loading changes that bring mobile LCP down.
Why mobile LCP is worse than desktop
LCP is the time from the start of navigation until the largest image or text block in the viewport finishes painting. To pass, 75% of visits must reach it in 2.5 seconds or less. On mobile, several things work against you at once:
- Slower processors. A mid-range phone can take several times longer than a laptop to parse HTML, run JavaScript and lay out the page. PageSpeed Insights simulates this with a slowed-down CPU on its mobile test.
- Slower networks. Mobile connections have higher latency, so every round trip costs more. A redirect or a late-discovered file hurts far more on 4G than on office broadband.
- A different main element. Responsive layouts often stack content, so the element that fills the first screen on a phone may be a different image, a heading or even a cookie banner.
- Oversized images. Many sites send the same 2,000-pixel hero to a 400-pixel screen, so phones download several times more data than they can show.
The fix is always to make the main element arrive sooner and render sooner. Which change does that depends on where the time is going, so measure before you change anything. The LCP guide covers the metric in depth, and the mobile Core Web Vitals guide covers all three metrics on phones.
How to find the LCP element and the slow stage
Run PageSpeed Insights on the URL with the Mobile tab selected. First read the field data at the top, which shows real visitors. Then scroll to the diagnostics and find the Largest Contentful Paint element entry, which names the element and shows a breakdown of its time.
| Stage | What it means | Usual fix on mobile |
|---|---|---|
| Time to First Byte | Waiting for the HTML | Page caching, a CDN for HTML, fewer redirects |
| Resource load delay | The browser found the image late | Remove lazy loading, use an img tag, add fetchpriority |
| Resource load duration | The image took long to download | Smaller files with srcset, sizes, WebP or AVIF |
| Element render delay | Downloaded, but not yet drawn | Less render-blocking CSS and JavaScript, better fonts |
To see the element on your own machine, open Chrome DevTools, switch on the device toolbar with a phone-sized screen, set CPU throttling to 4x slowdown and the network to Slow 4G in the Performance panel, and paste this into the Console before reloading:
new PerformanceObserver((list) => {
const e = list.getEntries().at(-1);
console.log('LCP', Math.round(e.startTime), 'ms', e.element, e.url || '(text)');
}).observe({ type: 'largest-contentful-paint', buffered: true });
The last line logged is the LCP element. If it shows a URL, the element is an image; if it shows text, it is a heading or paragraph, and the image stages do not apply. Then record a load in the Performance panel and open the LCP insight to see the stages as bars.
The key HTML changes for the hero image
Most mobile LCP problems are fixed in the markup of one element. This is a hero image written well for phones:
<img
src="/img/hero-800.webp"
srcset="/img/hero-400.webp 400w, /img/hero-800.webp 800w,
/img/hero-1200.webp 1200w, /img/hero-1600.webp 1600w"
sizes="100vw"
width="1600" height="900"
alt="Fitted kitchen in oak and white"
fetchpriority="high"
decoding="async">
- No
loading="lazy". Lazy loading tells the browser to wait, which is the opposite of what the main image needs. Remove it from anything visible on first load. See loading lazy not working for how to apply it correctly further down. fetchpriority="high"moves the image ahead of other images in the download queue. It is supported in current Chrome, Edge, Safari and Firefox, and older browsers simply ignore it.srcsetandsizeslet a phone pick the 400 or 800 pixel file instead of the largest. Setsizesto how wide the image really displays;100vwmeans the full screen width.widthandheightreserve the space and prevent layout shift.
When the image is found late
If the hero is a CSS background, or is added by a slider script, the browser cannot see it in the HTML. The best fix is to change it to an img element. If you cannot, preload it in the head, with the same responsive set so phones fetch the small file:
<link rel="preload" as="image" fetchpriority="high"
href="https://example.com/img/hero-800.webp"
imagesrcset="/img/hero-400.webp 400w, /img/hero-800.webp 800w, /img/hero-1200.webp 1200w"
imagesizes="100vw">
Render delay, fonts and the server
If the breakdown shows a long element render delay, the image or text has arrived but the browser is not yet allowed to draw it. On phones this usually comes from large stylesheets and scripts in the head, which must be downloaded and processed before the first paint. Defer scripts that are not needed for the first screen, and keep the head small:
<!-- Blocks the first paint -->
<script src="/js/slider.js"></script>
<!-- Downloads in parallel and runs after the HTML is parsed -->
<script src="/js/slider.js" defer></script>
When the LCP element is a heading, a web font can hold it back. Use font-display: swap so text shows in a fallback font straight away, and preload only the one font file used above the fold. The render-blocking resources guide covers critical CSS and script loading in more detail.
If the first stage, TTFB, is the largest, nothing in the page can fix it. Page caching and a CDN that caches HTML help mobile visitors most, because each round trip costs them more. The high TTFB guide shows how to measure and reduce it.
Platform notes
- WordPress: WordPress core skips lazy loading on the first content image and can add
fetchpriority="high"to it, but themes, page builders and optimisation plugins often override this. Check the final HTML of the hero. Page builder sliders are a frequent cause of late discovery. See Core Web Vitals on WordPress. - Shopify: in Liquid, use the
image_tagfilter withwidths,sizesandpreload: trueorfetchpriority: 'high'on the hero section, and remove lazy loading from it. Many themes have a setting for the first section. - Next.js: give the hero
next/imagecomponent thepriorityprop, orpreloadin newer versions, and set a correctsizesvalue. - Cloudflare and image CDNs: use automatic format and resizing so phones receive WebP or AVIF at the right width.
A worked example
A local builder's home page passes LCP on desktop at 1.8 seconds but fails on mobile at 4.1 seconds in the lab, with real-visitor LCP at 3.8 seconds. PageSpeed Insights names a div with the class hero-banner as the LCP element, and the breakdown shows a resource load delay of nearly two seconds.
The hero photo is set as a CSS background on that div, so the browser only discovers it after the 180 KB stylesheet has loaded and been matched to the element. The file is a 2,400-pixel JPEG of 620 KB, sent to every screen size.
The team replaces the background with an img element using a four-size WebP srcset, sizes="100vw" and fetchpriority="high", and adds a matching preload for the mobile sizes. Phones now download a 48 KB file that starts in the first few hundred milliseconds. Lab mobile LCP drops to 2.2 seconds, and after four weeks the field figure passes at 2.3 seconds.
The fix, step by step
Step 1
Find the mobile LCP element
Run PageSpeed Insights on the page with the Mobile tab selected and find the Largest Contentful Paint element entry in the diagnostics. Note which element it names, whether it is an image or text, and which of the four stages takes the longest. Confirm in Chrome DevTools with a phone-sized screen, throttling turned on and the PerformanceObserver snippet in the Console. Every following step depends on knowing this element, so do not skip it.
Step 2
Remove lazy loading from the hero
Inspect the LCP image in the final HTML, not the editor, and remove loading="lazy" if it is there. Check your theme, page builder and optimisation plugin settings, since they often add it to every image; most have an option to exclude the first images or a specific class. Also remove it from anything else visible on the first screen. Reload and confirm in the Network panel that the hero image is requested early, close to the stylesheets.
Step 3
Add fetchpriority high
Add fetchpriority="high" to the LCP image so the browser downloads it before other images. Use it on one image only, since marking several as high priority cancels the benefit. On Next.js use the priority prop on the image component, and on Shopify set it in the image_tag filter. Confirm in the Network panel with the Priority column turned on that the hero image now shows High from the start rather than Low.
Step 4
Use an img element, not a background
If the LCP element is a div with a CSS background image, replace the background with an img element inside it, positioned with object-fit: cover if you need it to fill the area. The browser can then find the image as soon as the HTML arrives instead of after the stylesheet loads. If you cannot change the markup, add a link rel="preload" with imagesrcset in the head. Confirm that resource load delay drops in the PageSpeed Insights breakdown.
Step 5
Send phones a smaller image
Create the hero in several widths, for example 400, 800, 1200 and 1600 pixels, in WebP or AVIF, and list them in srcset with a sizes value that matches how wide the image displays. Keep each mobile file well under 100 KB where you can. Add width and height to prevent layout shift. Confirm in the DevTools Network panel with a phone-sized screen that the browser downloads the small file and not the largest one.
Step 6
Reduce render-blocking files
Look at the Render-blocking requests or render-blocking resources audit in the mobile report. Add defer to scripts that are not needed for the first screen, remove unused plugins that add CSS to every page, and consider inlining a small amount of critical CSS. For a text LCP element, use font-display: swap and preload only the main font. Retest and confirm the element render delay in the LCP breakdown has dropped.
Step 7
Fix server response time
If Time to First Byte is the largest part of mobile LCP, the page cannot start drawing until the HTML arrives. Measure it with curl and the time_starttransfer value, turn on full-page caching for anonymous visitors, remove any redirect hops before the final URL and consider a CDN that caches HTML near your visitors. Confirm that the TTFB stage in the LCP breakdown falls, and that your cache status header shows a hit.
Step 8
Retest and watch field data
Run the mobile test in PageSpeed Insights three times and use the middle result, since single runs vary. Then test on a real mid-range phone over mobile data. Once lab results are consistently under 2.5 seconds, watch the field data and the mobile Core Web Vitals report in Google Search Console over the following weeks. The field figure covers 28 days, so allow up to a month before judging whether the fix reached real visitors.
Edge cases worth knowing
- Images hidden on mobile. A desktop hero hidden with
display: noneon phones is often still downloaded. Use apictureelement with media conditions, or remove it from the mobile layout, so phones do not pay for an image they never show. - Sliders and carousels. A slider usually loads several large images and a script before showing the first slide. A single static hero is almost always faster.
- Cookie banners as LCP. On small screens a large consent banner can become the LCP element. Keep its text short so it does not become the largest element.
- Text LCP and fonts. If a heading is the LCP element, image fixes will not help; look at render-blocking CSS and fonts.
- Lab and field disagree. The lab test uses one simulated phone. Real visitors use many devices, so field data can be better or worse than the lab result.
Keeping mobile LCP fast
Treat the first screen on mobile as a protected area. Before publishing a new landing page or theme change, check that the hero image is an img with a responsive srcset, has no lazy loading and carries fetchpriority="high", and that no new script has been added to the head. Run the mobile test in PageSpeed Insights for each main template after any change.
Field data in PageSpeed Insights covers the previous 28 days, so improvements show gradually. Check the Core Web Vitals report in Google Search Console every month and look at the mobile report first, since that is usually where URL groups fail.
1. Why is my LCP good on desktop but bad on mobile?
LCP is usually worse on mobile because phones have slower processors and higher-latency networks, and because the mobile layout often has a different or larger main element. A hero image that is found late or sent at full desktop size costs a phone far more time than a laptop. The mobile test in PageSpeed Insights also simulates a slow phone and network. Check which element is the LCP on mobile, because it is often not the same as on desktop.
2. What is a good LCP on mobile?
A good LCP on mobile is 2.5 seconds or less for at least 75% of real visits, the same threshold as on desktop. Values between 2.5 and 4 seconds need improvement, and anything over 4 seconds is poor. Google assesses mobile and desktop separately, so a page can pass on one and fail on the other. Aim for a lab result comfortably under 2.5 seconds on the mobile test, because real visitors on older phones are often slower than the lab.
3. Should I lazy-load my hero image?
No, you should not lazy-load the hero image or anything else visible when the page first loads. Lazy loading tells the browser to delay fetching the image until it knows the image is near the viewport, which pushes back LCP. Use lazy loading for images further down the page, where it saves data and bandwidth. For the hero, remove the lazy attribute, add fetchpriority high and make sure the image is in the HTML rather than added later by a script.
4. Does fetchpriority high really help LCP?
Yes, fetchpriority high often helps LCP when the main image would otherwise wait behind other files. By default, Chrome starts images at a low priority until it knows they are in the viewport, so the hero can queue behind scripts, fonts and other images. Marking it as high priority lets it start sooner. The gain is largest on mobile, where bandwidth is limited. It does not help if the image is found late or is far too large.
5. Should I preload the LCP image?
You should preload the LCP image only when the browser cannot find it early in the HTML, for example when it is a CSS background or is inserted by JavaScript. If the image is already an img element near the top of the HTML, fetchpriority high is usually enough and a preload adds little. When you do preload, use imagesrcset and imagesizes so phones fetch the small version, and never preload more than the one main image.
6. Why does PageSpeed Insights show different mobile LCP each time?
Lab results vary between runs because network conditions, server response times and third-party scripts change from moment to moment. A difference of several hundred milliseconds between runs is normal. Run the test three to five times and use the middle result when comparing before and after a change. If results swing by seconds, look for something inconsistent, such as a server that is sometimes slow, an uncached page or an advert that loads at a different size each time.
7. How long does it take for mobile LCP to improve in Search Console?
Improvements usually take around four weeks to show fully in Search Console, because the Core Web Vitals report is based on a rolling 28-day window of real Chrome user data. The field data in PageSpeed Insights uses the same window. Lab tests show the change immediately, so use them to confirm the fix works. If a URL group has failed, you can use the validate fix option in the report, which monitors it over the following 28 days.
The Core Web Vitals checker on aiwebpageseo.com shows mobile field results, the LCP element and how its time splits into stages, so you know which change will help before you make it.
Open Core Web Vitals Fixes โ