Largest Contentful Paint (LCP)
What LCP measures, its thresholds, the four sub-parts that make it up, and how to actually improve it — the Core Web Vital people struggle with most.
Largest Contentful Paint (LCP) is the render time of the largest image or text block visible in the viewport, relative to when the page started loading. Good is ≤2.5 s at the 75th percentile of real users; it's one of the three Core Web Vitals. It breaks into four sub-parts — TTFB, resource load delay, resource load duration, and element render delay — and TTFB plus load duration usually dominate. The biggest wins: don't lazy-load the LCP image, give it fetchpriority=high, preload it, cut render-blocking resources, and fix TTFB. It's a field metric — lab tools only approximate it — and of the Core Web Vitals it's the one people struggle most to pass, especially on mobile.
TL;DR — Largest Contentful Paint (LCP) measures how long it takes for the biggest thing on screen — usually a hero image or a big block of text — to show up after someone clicks to your page. Under 2.5 seconds is good. It’s one of Google’s three Core Web Vitals, and it’s the one most sites struggle with.
What LCP is
The first impression people have of your site is how fast it appears to load. LCP tries to put a number on that. It measures the amount of time it takes to load the single largest visible element in the viewport — the part of the page you can see without scrolling.
That “largest element” is usually one of two things:
- A big image — a hero banner, a product photo, a featured image.
- A big block of text — common on article pages that don’t lead with an image.
LCP is the moment that element finishes rendering, measured from when the page first started loading. The lower the number, the faster your page feels.
The score
Google sorts LCP into three buckets:
- Good: 2.5 seconds or less
- Needs improvement: 2.5 to 4 seconds
- Poor: more than 4 seconds
You’re aiming for that 2.5-second mark. And it’s judged on real visitors to your site, not a test you run once — so it’s the experience your actual audience gets on their actual phones and connections.
Evidence for this claim A good LCP is 2.5 seconds or less at the 75th percentile of page loads, segmented by device type. Scope: Current web.dev LCP field threshold and assessment method. Confidence: high · Verified: web.dev: Largest Contentful PaintWhy it can be hard
LCP is the Core Web Vital people struggle with the most. That’s because it has the most moving parts: your server has to respond, the browser has to find and download the image, and then it has to actually paint it. A slowdown at any of those steps drags the whole number up. Compressing your images is a common first guess — and it sometimes helps — but it’s often not the real bottleneck.
It’s also harder on mobile than desktop, because phones have slower connections and less processing power.
What to do first
Three quick wins that fix the most common mistakes:
- Don’t lazy-load your main image. “Lazy loading” tells the browser to wait before fetching an image. That’s great for stuff far down the page — but if you do it to your hero image, you’re deliberately delaying the most important thing on screen. Evidence for this claim An LCP image should not be lazy-loaded, and reducing resource load delay is a primary LCP optimization. Scope: web.dev guidance for image-based LCP elements. Confidence: high · Verified: web.dev: Optimize LCP
- Tell the browser the main image is important — there’s an attribute
(
fetchpriority="high") that does exactly that. Put it on the one image that’s actually your LCP candidate; slapping it on several images dilutes the signal. - Speed up your server. If your server is slow to respond, nothing else you do matters much.
Want the full mental model — the four sub-parts of LCP, how to find your LCP element, the rendering and font stuff, and how much this actually matters for rankings? Switch to the Advanced tab.
TL;DR — LCP is the render time of the largest image or text block visible in the viewport, relative to when the page started loading. Good is ≤ 2.5 s at the 75th percentile of real users (split by device); 2.5–4 s needs work, over 4 s is poor. It’s one of three Core Web Vitals and breaks into four sub-parts — TTFB, resource load delay, resource load duration, element render delay — where TTFB and load duration usually dominate (guidelines, not fixed shares — diagnose your own page). Top fixes: never lazy-load the LCP image, add
fetchpriority="high"on the actual candidate, preload it when it isn’t in the HTML, kill render-blocking CSS/JS, and fix TTFB. It’s a field metric — lab tools only approximate it — and the LCP element can change during load. Google confirms Core Web Vitals feed ranking systems but doesn’t publish an exact LCP weight or call it a tiebreaker; content relevance still dominates.
What LCP actually measures
LCP reports the render time of the largest image or text block visible in the viewport, measured relative to when the user first navigated to the page. Google’s own framing: it’s the closest standardized proxy for when the main content appears to the user. It replaced earlier, fuzzier metrics like First Meaningful Paint and Speed Index.
A few things that trip people up right away:
- It’s not “page load time.” A page can have every resource fetched and still post a slow LCP if rendering the largest element was blocked. LCP is about that one element, not the whole page.
- It’s not the same as FCP. First Contentful Paint fires when any content first appears; LCP waits for the largest element. A page can have a fast FCP (the navbar paints) and a slow LCP (the hero image loads late).
- It’s a dynamic metric. The browser dispatches a new LCP candidate every time a larger element becomes visible. The last entry before the user interacts (tap, scroll, keypress) or the page unloads is the value that counts — interaction often changes what’s visible, so reporting stops there. A candidate that’s later removed from the DOM doesn’t erase its own entry — it stays the reported element unless a still-larger one renders before reporting stops.
The thresholds — and why 2.5 seconds
| Bucket | LCP |
|---|---|
| Good | ≤ 2.5 s |
| Needs improvement | 2.5 s – 4.0 s |
| Poor | > 4.0 s |
Assessed at the 75th percentile of real-user page loads, segmented by device type. So three out of four visits need to come in under 2.5 s for an origin to pass.
Evidence for this claim A good LCP is 2.5 seconds or less at the 75th percentile of page loads, segmented by device type. Scope: Current web.dev LCP field threshold and assessment method. Confidence: high · Verified: web.dev: Largest Contentful PaintWhy 2.5 specifically? Google’s threshold methodology leaned on two things: human perception research pointing at roughly 1–3 seconds as the band that feels “immediate,” and CrUX achievability data showing 2.5 s was consistently achievable for well-optimized sites without being trivially easy. Tighter targets like 1.5 s or 2.0 s weren’t consistently achievable across enough origins, so they didn’t make the cut.
What counts as the LCP element
The element types considered for LCP:
<img>elements<image>elements inside an<svg><video>elements (the poster image load time, or the first frame, whichever is earlier)- An element with a background image loaded via the CSS
url()function - Block-level elements containing text nodes or other inline text children
The reported size is what’s actually visible in the viewport — portions clipped
or scrolled off don’t count, and for images it’s the visible size or the intrinsic
size, whichever is smaller. Margins, padding, and borders are ignored. A handful of
elements get excluded by heuristics: anything with opacity: 0, elements that
cover the whole viewport (treated as backgrounds), and low-entropy placeholder
images.
About three-quarters of pages have an image as their LCP element — so image work is usually the right first move. But not always, and not always compression (more on that next). The remaining chunk are text LCPs, where the lever is entirely different: it’s font loading, not image weight.
The four sub-parts — the part most articles skip
This is the framework I’d start any LCP diagnosis with. web.dev breaks LCP into four sequential sub-parts:
- Time to First Byte (TTFB) — from when the user starts loading the page to when the browser receives the first byte of HTML. Typical share: ~40% of total LCP.
- Resource load delay — the gap between TTFB and the browser starting to load the LCP resource. This is discovery time. Typical share: under 10%.
- Resource load duration — how long the LCP resource itself takes to download. Typical share: ~40%.
- Element render delay — from when the resource finishes loading to when the element actually paints. Typical share: under 10%.
| LCP sub-part | Typical share of total LCP |
|---|---|
| Time to First Byte | ~40% |
| Resource load delay | < 10% |
| Resource load duration | ~40% |
| Element render delay | < 10% |
The principle behind the table: the vast majority of LCP time should be spent loading the HTML document and the LCP resource. Any stretch where neither is loading is an opportunity to improve.
web.dev is explicit that these percentages are guidelines, not strict rules — don’t convert them into absolute-second targets, and don’t force every page to match the split. They’re only meaningful relative to each other, and if your LCP is consistently within 2.5 seconds already, the relative proportions don’t matter at all. Use the table to spot which sub-part is eating an outsized share on your page, then fix that one — not to chase an exact 40/10/40/10 split.
Evidence for this claim An LCP image should not be lazy-loaded, and reducing resource load delay is a primary LCP optimization. Scope: web.dev guidance for image-based LCP elements. Confidence: high · Verified: web.dev: Optimize LCPThe timeline begins with Time to First Byte, targeted at roughly 40 percent of total LCP. Resource load delay follows and should remain under 10 percent. Resource load duration is targeted at roughly 40 percent. Element render delay should remain under 10 percent and ends when the largest element actually paints.
© Patrick Stox LLC · CC BY 4.0 ·
And here’s the bit that upends the common assumption: as of February 2025 these four sub-parts are available in the CrUX API for image LCPs, and the Chrome team’s analysis of HTTP Archive data found that image download time was often the smallest part of LCP time. In other words, “just compress my images” frequently fixes the wrong sub-part. TTFB and discovery delay are often the bigger levers.
How to find your LCP element
Before you optimize anything, find out which element is your LCP and which sub-part is the bottleneck:
- PageSpeed Insights — the Diagnostics section flags the LCP element, and the field-data tab shows your real-user score.
- Chrome DevTools — the Performance panel marks the LCP node on the timeline.
- The
web-vitalsJS library — log LCP (and the element) from your own real-user monitoring.
How to improve LCP
Map each fix to the sub-part it targets:
Fix resource load delay (discovery). This is the highest-leverage and most commonly broken one.
- Never lazy-load your LCP image.
loading="lazy"on the LCP element always adds unnecessary load delay. Reserve lazy loading for below-the-fold images. - Add
fetchpriority="high"to the likely LCP image so the browser fetches it early at high priority. - Preload it with
<link rel="preload">when the image isn’t discoverable in the initial HTML — for example, when it’s loaded via CSS or JavaScript. Loading the hero image via JS is an anti-pattern precisely because it hides the URL from the browser’s preload scanner. - Host critical resources on the same origin so the browser doesn’t pay extra connection setup.
Preload and fetchpriority solve different problems, so don’t reach for both by
habit. Preload exposes a resource the browser’s preload scanner would otherwise
discover late (a JS- or CSS-loaded image, for example); fetchpriority changes
the fetch priority of a resource the browser already found. If discovery and
priority are already correct — the image is a plain <img> in the initial HTML
— adding either can do little beyond extra requests. Check a trace, apply the one
that matches the actual problem, and confirm the field number moved.
Fix element render delay.
- Reduce or inline render-blocking CSS; defer non-critical styles.
- Avoid synchronous scripts in the
<head>. - Prefer server-side rendering or static generation so the markup arrives ready to paint, and break up long main-thread tasks.
Reduce resource load duration.
- Modern image formats (WebP, AVIF), sensible compression, and a CDN.
- Efficient
Cache-Control. And don’t ignore network contention — lazy-loading the other below-fold images can free up bandwidth so the LCP image lands sooner.
Reduce TTFB.
- Minimize redirects, drop unnecessary unique URL parameters, and optimize server response time. Note that LCP includes any unload time from the previous page, connection setup, and redirect time — all of which roll into TTFB.
Special case: text-based LCP. When the largest element is text, the critical
path is font loading, not image weight. font-display: optional or system
fonts eliminate font-induced render delay; font-display: swap without
preloading the font file can introduce it.
Lab vs. field — this distinction matters
LCP is fundamentally a field metric. Google assesses it on real users via CrUX, surfaced in PageSpeed Insights’ field tab and the Search Console Core Web Vitals report. That field data is what feeds rankings.
Lab tools — Lighthouse, Chrome DevTools, WebPageTest — only approximate it under simulated conditions, and they don’t even use the same scoring. Lighthouse applies stricter desktop thresholds (Good ≤ 1.2 s) than the field standard (≤ 2.5 s). So a passing Lighthouse score doesn’t guarantee a passing CrUX score, and vice versa. Use lab tools to debug and reproduce; trust the field data for the actual verdict.
There’s a second reason lab and field numbers can diverge, worth knowing so an odd
reading doesn’t send you chasing a phantom bug: the current LargestContentfulPaint
browser API (still a W3C Working Draft) is scoped to a single document load. It
doesn’t itself reset on back/forward cache (bfcache) restores or same-document SPA
navigations, and pages that start off-screen — background tabs, prerendered pages —
can report inflated values because timing runs from load rather than from when the
page actually became visible. The reporting algorithm also halts on qualifying user
input, so if a user interacts before your main content displays, LCP won’t capture
it. None of this changes the threshold table above; it explains why a specific
session’s number can look wrong when the underlying navigation isn’t a plain
first load.
Does LCP affect rankings?
Yes, in the sense that Google confirms Core Web Vitals feed its ranking systems and recommends achieving good scores. But current Search Central documentation doesn’t publish an exact LCP weight and doesn’t describe it as a tiebreaker — Google’s own framing is that page experience “can contribute to success in Search” for queries where multiple pages already offer comparable, relevant content, and that a good score doesn’t guarantee a ranking boost. Content relevance and quality still dominate. Optimize LCP because a faster-feeling page is genuinely better for users (and conversions) — not because the mechanism is documented as a rankings tiebreaker, because it isn’t.
Evidence for this claim Google says Core Web Vitals are used by ranking systems, but current documentation does not specify an LCP weight, tiebreaker rule, or ranking guarantee. Scope: ranking systems Confidence: high · Verified: Understanding page experience in Google Search resultsA couple of realities from the data: of the Core Web Vitals, LCP is the one sites struggle most to improve, and it’s noticeably harder on mobile than desktop — slower CPUs and connections. On 3G and slower, the 2.5 s threshold can feel almost impossible to hit.
Where this fits
LCP is one of three Core Web Vitals, alongside Interaction to Next Paint and Cumulative Layout Shift. Its first sub-part, Time to First Byte, is its own diagnostic metric, and First Contentful Paint sits right next to it on the loading timeline. You’ll see all of these in PageSpeed Insights, Lighthouse, and the Chrome User Experience Report (CrUX). Each is its own deep dive in this cluster.
AI summary
A condensed take on the Advanced version:
- LCP = render time of the largest visible image or text block, relative to when the page started loading. It’s the closest standardized proxy for “when does the main content appear.”
- Thresholds: Good ≤ 2.5 s, Needs improvement 2.5–4 s, Poor > 4 s — at the 75th percentile of real users, split by device. It’s one of three Core Web Vitals.
- Not page-load time, not FCP. FCP = first pixel of any content; LCP = the largest element. LCP is also dynamic — the largest candidate can change during load; the last one before user interaction counts.
- LCP elements:
<img>,<image>in<svg>,<video>poster, CSSbackground-image: url(), or a block-level text element. ~3 in 4 pages have an image LCP; the rest are text (where fonts, not image weight, are the lever). - Four sub-parts: TTFB (~40%), resource load delay (<10%), resource load duration (~40%), element render delay (<10%) — web.dev calls these guidelines, not fixed shares; diagnose per page rather than chasing an exact split. CrUX 2025 data: image download is often the smallest part — so “just compress images” often fixes the wrong thing.
- Top fixes: never lazy-load the LCP image; add
fetchpriority="high"on the actual candidate; preload it when it’s not in the HTML (preload andfetchprioritysolve different problems — don’t reach for both by habit); cut render-blocking CSS/JS; reduce TTFB. - Field, not lab. CrUX/Search Console drive rankings; Lighthouse only
approximates and uses stricter desktop thresholds (≤ 1.2 s). The current
LargestContentfulPaintAPI is scoped to document loads and doesn’t itself reset for bfcache restores or same-document SPA navigations. - Rankings: Google confirms CWV feed ranking systems but publishes no exact LCP weight and doesn’t call it a tiebreaker; content relevance still dominates. Hardest CWV to improve, and harder on mobile.
Official documentation
Primary-source guidance from Google’s Chrome and Search teams.
web.dev (Chrome team)
- Largest Contentful Paint (LCP) — the canonical definition: what counts as an LCP element, how size is calculated, when reporting stops, and the measurement APIs.
- Optimize Largest Contentful Paint — the four sub-parts framework and the full optimization playbook.
- Core Web Vitals — where LCP sits among the three Core Web Vitals.
- How the Core Web Vitals metrics thresholds were defined — the research and achievability data behind the 2.5 s mark.
Chrome for Developers
- LCP image subparts and RTT now available in CrUX — the Feb 2025 field-data release of the four sub-parts (image LCPs only).
- Largest Contentful Paint | Lighthouse — the lab metric and its device-specific scoring.
Google Search Central
- Understanding Core Web Vitals and Google search results — how Core Web Vitals factor into Search.
Quotes from the source
On-the-record statements from Google’s documentation and team. Each link is a deep link that jumps to the quoted passage.
web.dev — definition and behavior (Philip Walton & Barry Pollard, Google)
- “LCP reports the render time of the largest image, text block, or video visible in the viewport, measured relative to when the user first navigated to the page.” Jump to quote
- On what’s measured: “LCP doesn’t consider margins, paddings, or borders applied using CSS.” Jump to quote
- On when reporting stops: “The browser will stop reporting new entries as soon as the user interacts with the page (via a tap, scroll, or keypress), as user interaction often changes what’s visible to the user.” Jump to quote
- On what’s included in the timing: “It is important to note that LCP includes any unload time from the previous page, connection set up time, redirect time, and other Time To First Byte (TTFB) delays.” Jump to quote
web.dev — optimization (Philip Walton & Barry Pollard, Google)
- The single most important lazy-loading rule: “Never lazy-load your LCP image, as that will always lead to unnecessary resource load delay.” Jump to quote
- The principle behind the sub-part targets: “The vast majority of the LCP time should be spent loading the HTML document and LCP source.” Jump to quote
Google Search Central — rankings
- “We highly recommend site owners achieve good Core Web Vitals for success with Search and to ensure a great user experience generally.” (Relayed from the Search Central Core Web Vitals doc; confirm against the live page before treating as final.)
LCP fix checklist
Work it roughly top to bottom — discovery and TTFB first, because they’re usually the biggest, most commonly broken levers.
- Found the actual LCP element (PageSpeed Insights Diagnostics, DevTools
Performance panel, or the
web-vitalslibrary) — don’t optimize blind. - Checked the four sub-parts to see which one is the bottleneck before changing anything.
- LCP image is not
loading="lazy"(lazy loading belongs below the fold only). - LCP image has
fetchpriority="high". - LCP image is discoverable in the initial HTML — or preloaded
(
<link rel="preload">) if it’s loaded via CSS/JS. - Not loading the hero image via JavaScript (hides it from the preload scanner).
- Render-blocking CSS minimized/inlined; non-critical styles deferred.
- No synchronous scripts in the
<head>; long tasks broken up. - Modern image format (WebP/AVIF), sensible compression, served via a CDN with
good
Cache-Control. - Below-fold images lazy-loaded so they don’t contend for bandwidth with the LCP image.
- TTFB addressed: redirects minimized, server response optimized, junk URL params dropped.
- Text LCP? Using
font-display: optionalor system fonts, and preloading any swapped font file. - Verified against field data (CrUX / Search Console), not just a Lighthouse lab run.
LCP cheat sheet
Thresholds (75th percentile of real users, by device)
| Bucket | LCP |
|---|---|
| Good | ≤ 2.5 s |
| Needs improvement | 2.5 – 4.0 s |
| Poor | > 4.0 s |
The four sub-parts — what each is and the fix
| Sub-part | What it is | Typical share | Main levers |
|---|---|---|---|
| Time to First Byte | Click → first byte of HTML | ~40% | Faster server, fewer redirects, drop junk URL params |
| Resource load delay | TTFB → LCP resource starts loading | < 10% | fetchpriority="high", preload, no JS-loaded hero, no lazy-load |
| Resource load duration | LCP resource download time | ~40% | WebP/AVIF, compression, CDN, cut bandwidth contention |
| Element render delay | Resource done → element paints | < 10% | Cut render-blocking CSS/JS, SSR/static, fonts for text LCP |
What can be the LCP element
<img>·<image>inside<svg>·<video>poster · CSSbackground-image: url()· block-level text
Excluded by heuristic: opacity: 0, full-viewport “background” elements, low-entropy placeholders.
Fast facts
- LCP is a field metric (CrUX / Search Console drive rankings); Lighthouse only approximates and uses a stricter desktop Good of ≤ 1.2 s.
- The LCP element can change during load; the last candidate before user interaction counts.
- ~3 in 4 pages have an image LCP; the rest are text (fonts are the lever).
- Image download time is often the smallest sub-part — compression isn’t always the answer.
- LCP ≠ FCP; LCP ≠ total page load time.
Patrick's relevant free tools
- Page Speed Test & Core Web Vitals Checker — One sentence tells you whether a page passes Core Web Vitals and what to fix first — real Chrome user data (CrUX) with a Lighthouse lab fallback, mobile and desktop side by side, loudly-labeled data sources, and prioritized diagnostic fixes. Plus a bulk origin scorecard with CSV export.
- Core Web Vitals History & Competitor Comparison — Chart 40 weeks of real-Chrome-user Core Web Vitals — p75 LCP, INP, CLS, FCP, and TTFB from the Chrome UX Report — and compare up to 5 origins or URLs on one chart. Plus a competitor Leaderboard that ranks curated groups of SEO and page-speed tools on each metric. Pass/fail scorecards, mobile vs desktop, shareable links, CSV export.
- Hosting Checker — Find a domain's public IP network, CDN or edge platform, DNS and mail-host evidence, and response transfer facts without pretending a proxy reveals the origin.
Tools for measuring and fixing LCP
Field data (what rankings use)
- PageSpeed Insights — field tab shows your real-user CrUX LCP; Diagnostics flags the LCP element.
- Search Console — Core Web Vitals report — LCP status across your URLs, grouped, on real-user data.
- Chrome User Experience Report (CrUX) — the underlying field dataset; as of Feb 2025 includes the four image-LCP sub-parts via the API.
web-vitalsJS library — log LCP and the LCP element from your own real-user monitoring.
Lab data (for debugging)
- Lighthouse — quick lab LCP and an opportunities list (remember: stricter desktop thresholds than the field).
- Chrome DevTools — Performance panel — marks the LCP node and the full render timeline.
- WebPageTest — waterfall view for pinning down which sub-part is slow.
SEO crawlers
- Ahrefs Site Audit — surfaces Core Web Vitals / performance issues across the site at scale.
How the tools themselves score
A live example of the metric this page describes — well-known page-speed and monitoring services ranked on their own real-user mobile LCP (Chrome UX Report field data):
LCP fixes that target the wrong problem
Lazy-loading the hero image
loading="lazy" delays discovery of an above-the-fold image that is likely to become
LCP. Load it eagerly, give the likely candidate fetchpriority="high", and reserve
lazy loading for below-the-fold images.
Compressing every image before finding the bottleneck
Image download duration is only one of four LCP sub-parts and may be the smallest. Identify the LCP element and inspect TTFB, load delay, load duration, and render delay before choosing a fix.
Loading the hero through JavaScript
A JS-injected image hides its URL from the browser’s preload scanner and creates resource load delay. Put the image in the initial HTML or preload it when CSS or JS must own it.
Declaring victory from one Lighthouse run
Lighthouse is a controlled diagnostic, while Google’s CWV verdict comes from CrUX field data. Use lab runs to verify the mechanism and wait for real-user data to show whether the p75 outcome improved.
The LCP resource starts late
Symptom: a long gap appears between TTFB and the LCP resource request. Likely
cause: lazy loading, JS discovery, a CSS background image, or low fetch priority.
Fix: make the resource discoverable in initial HTML, remove lazy loading, apply
fetchpriority="high", or preload it. Confirm the request moves earlier in a trace.
The resource loads but LCP still fires late
Symptom: load duration ends well before the LCP event. Likely cause: render-blocking CSS, synchronous JavaScript, a long task, or font rendering for a text LCP. Fix: reduce blocking work and test font strategy for text; confirm element render delay shrinks.
Lab LCP is good but field LCP is poor
Symptom: Lighthouse passes while CrUX or Search Console does not. Likely cause: real users have different devices, networks, cache states, geography, or LCP elements. Fix: segment field data, capture RUM element/sub-part details, and reproduce the slow segment rather than tuning only the default lab profile.
The reported LCP element changes between runs
Symptom: DevTools identifies different images or text blocks. Likely cause: responsive breakpoints, personalization, late DOM changes, or competing candidates. Fix: test representative viewports and states, then optimize each recurring candidate instead of assuming one desktop hero covers every user.
Hero image discovery: delayed vs early
A simplified delayed implementation hides the image behind JavaScript:
<div id="hero"></div>
<script>
document.querySelector('#hero').innerHTML = '<img src="hero.webp" alt="">';
</script>The browser can discover and prioritize this version while parsing HTML:
<img src="hero.webp" alt="" fetchpriority="high" width="1200" height="675">CSS background image: undisclosed vs preloaded
When the LCP image must remain a CSS background, disclose it before the stylesheet finishes:
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">The preload only helps when its URL and request attributes match the actual resource.
List recent LCP candidates in Chrome DevTools
Paste this into the Chrome DevTools Console, reload the page, and watch each candidate the browser reports. The last candidate before interaction is the relevant one.
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.table({
lcp: Math.round(entry.startTime),
element: entry.element?.tagName,
url: entry.url || '',
size: entry.size,
});
}
}).observe({ type: 'largest-contentful-paint', buffered: true });Find likely lazy-loaded above-the-fold images
Run this in the DevTools Console. It lists lazy images whose top edge begins in the current viewport; verify the real LCP candidate before removing the attribute.
[...document.querySelectorAll('img[loading="lazy"]')]
.filter((img) => img.getBoundingClientRect().top < innerHeight)
.map((img) => ({ src: img.currentSrc || img.src, top: img.getBoundingClientRect().top }));Extract image priority attributes in a crawler
Use this XPath in Screaming Frog custom extraction to return images marked as high priority:
//img[@fetchpriority='high']/@src Prove an LCP fix landed
Discovery-order test
Test to run: record a DevTools Performance trace after changing the hero image. Expected result: the LCP request starts earlier and is not lazy-loaded. Failure interpretation: the resource remains hidden, deprioritized, or blocked behind another dependency. Monitoring window: immediate lab result. Rollback trigger: the change delays another critical resource or makes lab LCP consistently worse.
Render-delay test
Test to run: compare the LCP resource completion and LCP event in equivalent before/after traces. Expected result: element render delay shrinks without a new layout or visual regression. Failure interpretation: CSS, JavaScript, or fonts still block paint. Monitoring window: immediate across representative viewports. Rollback trigger: broken rendering, missing styles, or a worse recurring LCP.
Field-outcome test
Test to run: monitor URL-level CrUX or first-party RUM p75 LCP after deployment. Expected result: p75 moves toward or remains within the Good threshold without regressing INP or CLS. Failure interpretation: the lab case was not representative or another sub-part dominates real visits. Monitoring window: RUM can lead; CrUX needs its rolling 28-day window to turn over. Rollback trigger: a sustained field regression tied to the release.
LCP metrics worth tracking
Field p75 LCP
Metric: LCP at the 75th percentile by form factor. What it tells you: whether real users meet the Core Web Vitals loading threshold. How to pull it: CrUX, Search Console, or first-party RUM. Benchmark / realistic range: Good is at or below 2.5 seconds; segment mobile and desktop. Cadence: weekly, with the CrUX rolling window recorded.
LCP sub-part distribution
Metric: TTFB, resource load delay, load duration, and element render delay for LCP. What it tells you: which stage owns the wait. How to pull it: representative lab traces and image-LCP subparts from CrUX/RUM where available. Benchmark / realistic range: use the article’s approximate 40/10/40/10 diagnostic split as a guide, not a universal performance promise. Cadence: after template releases and monthly for priority templates.
Good-LCP URL coverage
Metric: important URL groups with Good field LCP. What it tells you: whether improvement is broad or limited to a sample page. How to pull it: Search Console CWV groups plus URL-level CrUX for priority pages. Benchmark / realistic range: establish a baseline by template; low-traffic URLs may lack individual field data. Cadence: weekly.
Test yourself: Largest Contentful Paint
Five quick questions on LCP measurement and diagnosis. Pick an answer for each, then check.
Resources worth your time
My related writing
- What Is Largest Contentful Paint (LCP) & How To Improve It — my full LCP guide on the Ahrefs blog.
- What Are Core Web Vitals (CWVs) & How To Improve Them — how LCP fits with INP and CLS, and why it’s the hardest to fix.
- The Beginner’s Guide to Technical SEO — where page performance sits in the bigger picture.
Official (Google / Chrome)
- Largest Contentful Paint (LCP) and Optimize LCP — the canonical pair.
- How CWV thresholds were defined — the why behind 2.5 s.
From others
- Fix your website’s Largest Contentful Paint by optimizing image loading — MDN’s developer-first take, strong on bandwidth contention and the JS-image anti-pattern.
- Performance — 2025 Web Almanac — HTTP Archive’s annual deep-dive; source for adoption stats on fetchpriority, preload usage, image vs text LCP splits, and pass rates by device.
- Largest Contentful Paint (LCP) — DebugBear’s docs cover waterfall analysis for pinpointing sub-parts, progressive JPEG caveats, and iframe/soft-navigation edge cases.
- Largest Contentful Paint (LCP): What It Is, How to Measure & Optimize — corewebvitals.io; real RUM benchmarks, business impact case studies (Vodafone Italy), and the Google Flights fetchpriority result.
- Largest Contentful Paint | MDN Web Docs — MDN reference for the LargestContentfulPaint API, element types, and browser compatibility.
Stats worth citing
- LCP is the hardest Core Web Vital to pass. It has the most components, which is why sites struggle with it more than INP or CLS. Source
- Mobile is harder than desktop. Slower CPUs and connections push LCP up, and on 3G/slow connections the 2.5 s threshold is nearly impossible to hit. Source
- Image download time is often the smallest part of LCP. Chrome’s analysis of HTTP Archive data found download duration frequently isn’t the bottleneck — TTFB and discovery delay usually are. Source
- CrUX coverage is thin. In our study of 42 million pages, only ~11.4% had associated CrUX field data — most pages don’t get enough real-user traffic to be measured. Source
- 62% of mobile pages vs 74% of desktop pages achieve Good LCP (2025 Web Almanac). The mobile gap reflects slower CPUs and network connections. Source
- Only 2.1% of mobile pages preload their LCP image, despite 76% having an image as their LCP element — a significant missed optimization opportunity (2025 Web Almanac). Source
fetchpriority="high"adoption grew from 0.03% of mobile sites in 2022 to 17.3% in 2025, largely driven by WordPress core adding it (2025 Web Almanac). Google Flights saw a 700 ms LCP improvement from this single attribute. Source
Videos
- Google Search Central (YouTube) — the Core Web Vitals and page-experience explainers, including Chrome team walkthroughs of LCP optimization. Channel
LCP
Largest Contentful Paint — render time of the largest visible image or text block, relative to when the page started loading. ≤2.5 s (at the 75th percentile) is good.
Related: Core Web Vitals, TTFB, FCP
LCP
Largest Contentful Paint (LCP) measures the render time of the largest image or text block visible in the viewport, relative to when the page first started loading. It’s the closest standardized approximation of when a page appears loaded to the user, and it’s one of Google’s three Core Web Vitals (alongside Interaction to Next Paint and Cumulative Layout Shift).
The scoring bands, measured at the 75th percentile of real-user page loads and split by device: Good ≤ 2.5 s, Needs Improvement 2.5–4.0 s, Poor > 4.0 s. The LCP element is usually an <img>, an image inside an <svg>, a <video> poster, a CSS background-image, or a block-level text element — and it can change during load, since the browser keeps reporting a new candidate each time a larger element paints, up until the first user interaction.
LCP is a field metric — Google assesses it on real users via the Chrome User Experience Report (CrUX), surfaced in PageSpeed Insights and Search Console. Lab tools like Lighthouse only approximate it. web.dev breaks LCP into four sub-parts — Time to First Byte, resource load delay, resource load duration, and element render delay — with TTFB and load duration usually dominating. The biggest fixes: don’t lazy-load the LCP image, give it fetchpriority="high", preload it when it isn’t in the initial HTML, cut render-blocking CSS/JS, and improve TTFB.
Related: Core Web Vitals, TTFB, FCP
Build-time retrieval analysis plus live signals for this exact article. The automatic chunk report includes a deterministic readiness score and is ready without a model download.
Search Console
sampleGA4 traffic (28d)
sampleCloudflare traffic (7d)
sampledCrUX field data (28d, phone)
sampleGoogle NLP entities
localChangelog
Updated Jul 18, 2026.
Editorial summary and recorded change details.Summary
Verified the LCP definition, thresholds, eligible-element list, and candidate-finalization behavior against the live web.dev and W3C sources, then fixed two overstated claims: the four sub-part percentages are now framed as web.dev's own 'guidelines, not strict rules' instead of fixed targets, and the ranking section drops the unsupported 'tiebreaker' characterization for Google's actual documented boundary (used by ranking systems, no published weight or guarantee). Added a note on current LCP API limitations (bfcache, SPA navigation, prerendering, early input) and a caveat that preload and fetchpriority solve different problems and shouldn't both be applied by habit.
Change details
-
Reframed the four LCP sub-part percentages (TTFB, resource load delay, resource load duration, element render delay) as diagnostic guidelines rather than fixed targets, per web.dev's explicit 'not strict rules' language, across the Advanced lens, cheat sheet, and AI summary.
-
Replaced the 'tiebreaker' ranking characterization with Google's actual documented position: Core Web Vitals feed ranking systems but carry no published weight or ranking guarantee.
-
Added a Lab vs. field paragraph on current LargestContentfulPaint API limitations (bfcache restores, same-document SPA navigation, prerendering/background tabs, early user input).
-
Added a preload-vs-fetchpriority distinction paragraph so readers don't apply both by habit when only one addresses the actual bottleneck.
Full comparison unavailable — no prior snapshot was archived for this revision.