MobileCheck

Largest Contentful Paint: How to Improve LCP on Mobile

Updated October 17, 2026 · Covers: Main content appears slowly

What it means

Largest Contentful Paint (LCP) is the time from the start of navigation until the biggest piece of content in the first screen is drawn. It is a stand-in for the moment a visitor feels "the page is here". On most mobile pages the LCP element is a hero image, a product photo, or the main headline or first paragraph when there is no large image.

Elements that can count as the LCP candidate:

Only the visible part inside the viewport counts, so an image that is mostly below the fold is measured by its on-screen area. The browser keeps updating the candidate as larger elements render and stops once the visitor taps, scrolls or presses a key. Because a phone screen is narrow, the LCP element on mobile is often different from the one on desktop: a headline that wins on a wide screen may lose to a full-width photo on a phone.

Why it matters

LCP is one of Google's three Core Web Vitals. The thresholds are:

LCPRating
2.5 s or lessGood
2.5–4 sNeeds improvement
Over 4 sPoor

Google assesses these at the 75th percentile of real visits, so most of your visitors should see the main content within 2.5 seconds. More practically, a slow LCP means people look at a blank area or a spinner while the content they came for is still downloading. On a phone with a weak signal, that is when they hit the back button.

How MobileCheck measures it

MobileCheck loads your page in a real browser engine for each device you pick and records LCP with the browser's own performance API. If the value is over 2.5 seconds, the report shows Main content appears slowly and labels it "needs improvement"; over 4 seconds it is marked "poor".

Be clear about what this number is: a lab measurement from a single load per device, made from our servers. Real visitors have different phones, networks, cache states and distances from your server. Lab data is great for spotting a problem and confirming a fix; field data (collected from real Chrome users and shown in PageSpeed Insights when your site has enough traffic) is what Google uses for Core Web Vitals. A single run can also vary, so if a result is close to the threshold, run the check again before drawing conclusions.

The LCP API comes from Chromium, which is also what Google's field data is based on, so the Android devices in your report are the closest match to how Google sees your pages.

The four parts of LCP

Every LCP time can be split into four sub-parts. Finding the largest one tells you where to focus:

  1. Time to First Byte (TTFB) — from the start of navigation until the first byte of HTML arrives. Slow hosting, uncached server rendering and redirects live here.
  2. Resource load delay — the gap between TTFB and the moment the browser starts downloading the LCP image. It grows when the image is discovered late: set by JavaScript, hidden in a CSS background, or lazy-loaded.
  3. Resource load duration — how long the image itself takes to download. Large files and slow connections dominate here.
  4. Element render delay — the time from the download finishing until the element is actually painted. Render-blocking CSS and JavaScript, web fonts holding back text, or client-side rendering that hasn't run yet all add to it.

For a text LCP element there is no resource to load, so only TTFB and render delay apply. Chrome DevTools shows this breakdown in the Performance panel when you record a page load.

How to fix it

Let the browser find the hero image early

Put the LCP image in the HTML as a normal <img> and give it high priority. Never lazy-load it: loading="lazy" on an above-the-fold image delays the download until layout is done.

<img src="/img/hero-800.avif"
     width="800" height="500"
     fetchpriority="high"
     alt="Team at work in the studio">

If the image is a CSS background or is inserted by a script, the browser can't see it while parsing the HTML. Preload it in the <head>:

<link rel="preload" as="image" href="/img/hero-800.avif"
      fetchpriority="high">

Serve the right size and format

A phone that is 390 CSS pixels wide at 3x density needs an image roughly 1170 pixels wide at most, not a 3000-pixel original. Use srcset and sizes so each device downloads a suitable file, and modern formats such as AVIF or WebP, which are usually much smaller than JPEG at similar quality.

<picture>
  <source type="image/avif"
          srcset="/img/hero-480.avif 480w, /img/hero-800.avif 800w, /img/hero-1200.avif 1200w"
          sizes="100vw">
  <img src="/img/hero-800.jpg"
       srcset="/img/hero-480.jpg 480w, /img/hero-800.jpg 800w, /img/hero-1200.jpg 1200w"
       sizes="100vw" width="1200" height="750"
       fetchpriority="high" alt="Team at work in the studio">
</picture>

If your images are much larger than they need to be, the page weight guide covers compression in more detail.

Cut server response time

If TTFB is the big part, no amount of image tuning will help. Cache full HTML pages where you can (page caching in your CMS, or at a CDN edge), avoid redirect chains such as http → https → www, and serve static assets from a CDN close to your visitors.

Remove render-blocking resources

Stylesheets and synchronous scripts in the <head> must be downloaded before anything is painted. Load scripts with defer (or async for independent ones), keep critical CSS small, and move non-essential third-party tags out of the head.

<script src="/js/app.js" defer></script>

Don't let fonts hide your text

When the LCP element is a headline, a web font that is still downloading can keep it invisible. font-display: swap shows the text in a fallback font right away and swaps it in later. Preloading the one or two fonts used above the fold also helps. See web fonts that fail to load for related problems.

@font-face {
  font-family: "Brand";
  src: url("/fonts/brand.woff2") format("woff2");
  font-display: swap;
}

Swapping fonts can move text around slightly. If that causes layout shift, match the fallback with size-adjust, as described in the layout shift guide.

Avoid rendering the main content only in JavaScript

If the hero is built by a client-side framework after a large bundle downloads and runs, the LCP waits for all of that. Server-side rendering or static generation puts the content in the initial HTML so it can paint as soon as it arrives.

How to check the fix

  1. Run the free mobile check again on the same devices and compare the LCP value in the report. Repeat once or twice if you are near 2.5 s, since single runs vary.
  2. In Chrome DevTools, record a page load in the Performance panel with network and CPU throttling to see which element is the LCP and which sub-part is largest.
  3. Open PageSpeed Insights for your URL to see field data from real Chrome users, if your site has enough traffic. Field data updates over a rolling 28-day window, so improvements show up gradually.

For a broader picture of how your page looks and behaves on different screens, see the responsive design checker.

Frequently asked questions

What is a good LCP score on mobile?

Google rates LCP of 2.5 seconds or less as good, 2.5 to 4 seconds as needing improvement, and over 4 seconds as poor, measured at the 75th percentile of real visits.

Why is my MobileCheck LCP different from PageSpeed Insights?

MobileCheck takes a lab measurement from one load per device on our servers. PageSpeed Insights shows a separate lab test plus field data from real Chrome users, so numbers differ with network, device and cache conditions.

Should I lazy-load my hero image?

No. Lazy-loading the image that becomes the LCP element delays its download. Load it normally, and add fetchpriority="high" so the browser fetches it early.

Related guides