Largest Contentful Paint: what slows it and what fixes it
You want Largest Contentful Paint at or below 2.5 seconds. You fix it by removing delay before the hero appears. This guide shows what the element usually is, the four parts of the time, the fixes in the right order, and how to read it in lab and field data.
By Théophile Louvart, founder of Porteur · Updated 13 September 2026 · Markdown
What Largest Contentful Paint measures
Largest Contentful Paint is the time from navigation to when the main content is visible. It stops when the largest image or text block in the viewport paints.
- Good as of 2026: up to 2.5 seconds.
- Needs work: between 2.5 and 4 seconds.
- Poor: above 4 seconds.
On most product sites the LCP element is one of three things: the hero image, the H1 heading, or a promo block near the top. Background images loaded via CSS can be the LCP candidate too. Video posters can be the LCP candidate. On some pages the pricing table becomes the LCP element if it is the largest thing above the fold.
If your hero swaps size or content after load, the LCP candidate can switch. That resets the clock and makes LCP worse. Keep the main element stable and predictable in size.
The four parts of LCP time
Fix LCP by breaking it into parts. Each part adds delay. Remove the biggest one first.
- Server response: time to first byte. How fast your server sends the first HTML byte.
- Render blocking: time the browser waits on CSS and scripts before it can render layout and text.
- Resource load: time to fetch the LCP resource. Often the hero image. Includes DNS, connect, TLS and transfer.
- Render: time to decode, layout and paint the element once bytes are in. Includes font rendering for text LCP.
You will see all four in a waterfall in devtools or Lighthouse. LCP improves when you cut the longest part by a clear margin. Small tweaks spread across all parts rarely move you under 2.5 seconds.
How to find your LCP element and timing
Identify the element in lab
Open your page in Chrome, run Lighthouse. In the Performance report, find the LCP audit. Lighthouse highlights the LCP element in the screenshot and lists its selector. It also shows the LCP time and a breakdown timeline.
Check the waterfall
Open Chrome DevTools, Performance panel. Record a page load on a throttled connection. Look for the LCP marker. Expand it to see the candidate and the moments when blocking, loading and painting occurred.
Confirm in PageSpeed Insights
Paste the URL in PageSpeed Insights. If there is enough traffic, you will see field data for LCP from the last 28 days. Below that, the Lighthouse run shows the lab LCP and the element it saw.
Verify on slow pages
Repeat on the slowest templates. For a SaaS, try /, /pricing and /guides/getting-started. The LCP element may differ by template. Fix the worst first.
Fix order that works: server first
Start with server response. A slow time to first byte drags every metric, not just LCP. It hurts every page and every visit.
- Cache HTML for anonymous users. Cache the full page at the edge where you can. Serve /, /pricing and /guides/* from cache.
- Avoid cold starts for your home and pricing pages. Keep the process warm. Pre-build or render ahead where possible.
- Keep HTML small. Remove unused inline scripts, heavy inlined JSON and debug code. Compress with gzip or brotli.
- Put your origin close to users. If you sell in one country, serve from there. Use a CDN for static assets and, if possible, HTML.
- Keep database work off the request path. Precompute and store hero content and navigation data. Do not fetch it on every page view.
- Use HTTP/2 or HTTP/3 for better multiplexing. Serve assets over the same origin to avoid extra DNS and TLS handshakes.
A fixed page loads its HTML in well under a second, then starts rendering before images arrive. Your H1 appears fast, then the hero image fills in without blocking text paint.
Remove render blocking: CSS and scripts
The browser will not paint until it has the CSS it needs. It can also be held by synchronous scripts. Cut this blocking to let first render start sooner.
- Inline only the critical CSS for above the fold. Keep it small. Load the rest as a file with rel=preload as=style then rel=stylesheet fallback.
- Split large CSS. Load styles for below-the-fold sections later. Remove unused rules from frameworks.
- Defer non-critical scripts with defer. For scripts you can load after first paint, use async or load them later after the first user interaction.
- Do not use document.write. Avoid blocking inline scripts early in the head.
- Remove or delay A/B test, analytics and chat scripts that block render. Load them after LCP where you can.
- Use media attributes and disabled attributes to conditionally load stylesheets only when needed.
Run a test with all third parties turned off in a staging build. If LCP drops under 2.5 seconds, bring them back one by one. Keep the ones that do not block. Delay the rest.
Optimise the LCP image: size and priority
If your LCP is an image, fix that next. You want the right file, the right size, and top priority.
- Serve modern formats like AVIF or WebP with a JPEG fallback where needed.
- Serve a size close to the rendered size. Do not send a 3000 pixel image for a 1200 pixel slot.
- Use srcset and sizes so mobile gets a smaller file. Define width and height to avoid layout shift.
- Do not lazy load the LCP image. Remove loading=lazy if it is on the hero.
- Set fetchpriority=high on the LCP image so the browser starts it early.
- Preload the exact LCP image URL with rel=preload as=image. Preload must match the URL and type the browser will use.
- If the image is in CSS as a background, preload it or move it into an <img> so you can control priority and formats.
- Compress hard. Keep quality acceptable but do not ship heavy files.
<link rel="preload" as="image" href="/images/hero-pricing.avif" imagesrcset="/images/hero-pricing.avif 1x, /images/hero-pricing-2x.avif 2x" imagesizes="100vw">
<img src="/images/hero-pricing.avif"
srcset="/images/hero-pricing.avif 1x, /images/hero-pricing-2x.avif 2x"
sizes="(max-width: 768px) 100vw, 1200px"
width="1200" height="768" alt="Pricing overview"
fetchpriority="high">On /pricing, this turns a 1.9 MB hero into a 280 KB AVIF. The browser starts it before other images and paints the section sooner. LCP drops under the 2.5 second line on a mid-range phone.
If text is your LCP: fix fonts
If the H1 is the LCP element, font loading can delay paint. Avoid hiding text while custom fonts load. Let text render fast, then refine.
- Self host your font files. Serve only the used subsets and weights.
- Preload the exact WOFF2 files used by the H1 and body. Use rel=preload as=font type=font/woff2 with crossorigin when needed.
- Use font-display: swap so the browser shows fallback text, then swaps to the custom font without blocking LCP.
- Avoid layout jumps when the font swaps. Pick fallback fonts with similar metrics. Set font-size-adjust where supported.
- Do not load many families and weights. Keep it lean above the fold. Consider a system font for the hero if you still miss 2.5 seconds.
<link rel="preload" as="font" type="font/woff2" href="/fonts/brand-headline.woff2" crossorigin>
<style>
@font-face {
font-family: 'Brand Headline';
src: url('/fonts/brand-headline.woff2') format('woff2');
font-display: swap;
}
</style>A fixed page shows the H1 in a system font at once, then swaps to your brand font without shifting lines. The LCP timestamp lands on the first paint, not the swap.
Verify in Lighthouse and in the field
Lighthouse is lab data. It runs one simulated load, by default a mid-range phone on throttled 4G. Scores vary between runs. Use it to compare branches and changes.
- Lighthouse performance score weights LCP at 25%. Total Blocking Time is 30%, CLS is 25%, First Contentful Paint is 10% and Speed Index is 10%.
- Run at least three times. Take the median. Close other tabs. Use the same network each time.
- Use the filmstrip and the LCP marker to confirm the element and the moment it paints.
- Check the Opportunities and Diagnostics. They point to render blocking resources and unoptimised images that affect LCP.
Field data shows how real users load your pages. PageSpeed Insights shows it when there is enough traffic. It uses the 75th percentile of Chrome users over the last 28 days, by URL or by origin. Expect changes to take days to reflect across the window.
Check your key templates. If only one or two URLs carry most traffic, fix those first. If you have a blog with many URLs, origin-level data helps you see the trend on the whole site.
Single-page apps and client rendering
If you ship a single-page app, the first paint often waits on JavaScript. The more code you send, the later the LCP fires. You must cut the boot cost or render on the server.
- Use server-side rendering or static generation for public pages. Ship HTML for the hero and H1.
- Code split aggressively. Load only the code needed for the first view. Defer route and admin bundles.
- Hydrate below the fold later. Keep interactivity for the hero light so it does not delay paint.
- Avoid client-side fetch for content that could be in the HTML. Do not gate the hero on an API call.
- Guard third-party widgets behind user action. Do not load them on first paint.
On yourproduct.com, render / and /pricing on the server. Ship a 12 KB critical CSS inline. Defer the rest. LCP then depends on image size and not your JS bundle.
Common traps that keep LCP high
- Lazy loading the hero image. The browser will not fetch it until late. Remove loading=lazy on the LCP image.
- Preloading the wrong URL. If the browser selects a different srcset candidate, your preload is wasted. Preload the exact URL the browser will choose.
- Hiding text until fonts load. font-display: block or no font-display will delay the H1. Use swap.
- Injecting a larger element after first paint. The LCP candidate switches and the clock resets. Keep sizes fixed.
- Heavy hero carousels. They add scripts, layout and images. Use a single hero image for speed.
- Above-the-fold CSS that imports more CSS. @import in CSS delays the cascade. Link stylesheets directly.
- A/B testing tools that rewrite the hero. Client-side variants delay paint. Run tests server-side where you can.
- Cookie banners that push the hero down. They increase the LCP candidate height or block view. Keep them small or delayed.
Track Core Web Vitals together
Fixing LCP can change other vitals. Keep CLS at or below 0.1. Keep Interaction to Next Paint at or below 200 ms. INP replaced First Input Delay in March 2024. Check all three after each change.
As you optimise images and fonts, watch for layout jumps. As you split scripts, watch for long tasks that hurt interactivity. Balance the three. A page that loads its hero at 2.3 seconds but blocks input for 500 ms still fails the experience.
Questions
Cut server time first with caching and edge delivery. Remove render blocking CSS and scripts. Optimise the LCP image, remove lazy loading on it, and set fetchpriority=high. If text is the LCP, self host fonts, preload them, and use font-display: swap.
Good is up to 2.5 seconds as of 2026. Between 2.5 and 4 seconds needs work. Above 4 seconds is poor. Check the 75th percentile of field data over the last 28 days to judge a URL.
Both are load milestones that affect user experience. LCP is a Core Web Vital and is part of page experience signals. FCP is not a Core Web Vital, but it contributes to Lighthouse’s performance score and helps you diagnose render blocking.
There is no Core Web Vital threshold for FCP. Use it to spot render blocking and slow first paint. Aim to reduce it along with LCP, but judge success by LCP, CLS and INP in the field.
Lighthouse is one simulated run on a mid-range phone with throttled 4G. Field data is the 75th percentile of real Chrome users over 28 days, per URL or origin. Networks, devices and repeat visits vary, so the numbers rarely match exactly.
Run Lighthouse and click the LCP audit to see the element and selector. In DevTools, the Performance panel marks the LCP candidate. If the hero swaps source via srcset, confirm the exact URL the browser picked and preload that one.
Sources
Check my site, free
Paste your homepage URL to see which element is your LCP and what on-page fixes will cut its time, free, in about thirty seconds.
- Free check, no card
- Read-only, your own accounts
- Readable by your agent
Read next
- GuideCore Web Vitals for a product site: the three numbers
- ComparisonLighthouse vs PageSpeed Insights: lab and field
- GuideTechnical SEO checklist for a small site
- GuideWebsite conversion rate: from the visit to the signup
- GlossaryLargest Contentful Paint (LCP)
- GlossaryInteraction to Next Paint (INP)
- GuideFirst Contentful Paint: what it measures and what moves it
- GuideHow to improve Interaction to Next Paint