What is Largest Contentful Paint (LCP) and How to Improve ?

Last updated July 21, 2025

LCP (Largest Contentful Paint) measures the time it takes for the largest visible content element to render on screen — typically an image, video poster, or a block-level text element. It reflects the point at which the main content is likely visible to the user.

Improving LCP helps reduce perceived load time and boosts both UX and SEO. LCP is one of the three Core Web Vitals used in Google’s ranking algorithm, alongside FCP and CLS.

Common causes of poor LCP include:

  • Slow resource load times for images, videos, or large text blocks above the fold.
  • Client-side rendering delays that defer DOM updates.
  • Large image or video file sizes without compression or optimization.
  • Heavy JavaScript blocking the main thread.
  • Poor server response time (TTFB) or lack of caching/CDN strategies.

How LCP is Measured

LCP is the timestamp of when the browser renders the largest visible element in the viewport. This is typically one of the following:

  • Images — such as standard <img> elements or CSS background images (via url())
  • Poster images on <video> elements
  • Large block-level text elements — like <h1>, <h2>, or <p> headings above the fold

To measure LCP with the web-vitals library:

  1. import { onLCP } from 'web-vitals';
  2. onLCP(console.log);

Or natively with the Performance API:

  1. new PerformanceObserver((entryList) => {
  2.   for (const entry of entryList.getEntries()) {
  3.     if (entry.entryType === 'largest-contentful-paint') {
  4.       console.log('LCP:', entry.startTime);
  5.     }
  6.   }
  7. }).observe({ type: 'largest-contentful-paint', buffered: true });

What is a Good LCP Score?

  • Good: 2.5 seconds or less
  • Needs improvement: 2.5 – 4.0 seconds
  • Poor: Above 4.0 seconds
Score Scale
2.5s
4.0s

LCP should be measured at the 75th percentile across both mobile and desktop traffic.


How to Improve LCP

1. Optimize and Compress Images

Images are often the largest content elements on a page and a common LCP bottleneck. To reduce load time:

  • Use modern formats like WebP or AVIF instead of JPEG/PNG.
  • Resize large images to match their actual display size — don’t upload 3000px-wide images if only 800px are needed.
  • Compress images to reduce file size without visible quality loss.

If you're a developer, you can automate image optimization in your build process. Here's an example using Sharp in Node.js:

  1. // Convert JPG to WebP and resize
  2. sharp('hero.jpg')
  3.   .resize(1200) // target width in pixels
  4.   .webp({ quality: 80 })
  5.   .toFile('hero.webp');

Not a developer? You can still easily prepare images for the web using free tools like:

Always set width and height attributes on images to prevent layout shifts and improve LCP consistency.

2. Preload Critical Assets

Preload the largest image or font that is likely to be the LCP candidate.

  1. <link rel="preload" href="//cdn.testdom.io/images/hero.webp" as="image">

3. Serve Content Faster with Caching and CDNs

Fast delivery of static content is essential for a good LCP score. You can speed this up by:

  • Using a CDN to deliver assets from a server closer to the user
  • Enabling browser caching for repeat visits
  • Setting proper cache headers (Cache-Control, ETag, Expires)
ASP.NET Web.config
  1. <staticContent>
  2.   <clientCache cacheControlMode="UseMaxAge"
  3.        cacheControlMaxAge="7.00:00:00" />
  4. </staticContent>
Node.js (Express)
  1. // Cache static assets for 7 days
  2. app.use('/static', express.static('public', {
  3.   maxAge: '7d'
  4. }));
NGINX
location ~* \.(jpg|jpeg|png|gif|css|js|woff2)$ {expires 7d;add_header Cache-Control "public";
}
Apache .htaccess
  1. <IfModule mod_expires.c>
  2.   ExpiresActive On
  3.   ExpiresByType image/webp "access plus 7 days"
  4.   ExpiresByType text/css "access plus 7 days"
  5. </IfModule>
Cloudflare CDN
  • Enable "Cache Everything" on static routes
  • Use "Edge Cache TTL" rules
  • Enable Polish and Auto Minify

CDNs like Cloudflare, Vercel, or PageSpeed CDN offer automatic caching and delivery with zero setup.

4. Reduce JavaScript Execution Time

Split bundles using code-splitting and defer non-critical scripts to avoid blocking the main thread.

  1. // Example with dynamic import
  2. if (condition) {
  3.   import('./extra-features.js').then(initExtras);
  4. }

5. Use Server-side or Static Rendering

Render content on the server to avoid hydration delays on the client side.

  1. // Example: SSR with Next.js
  2. export async function getServerSideProps() {
  3.   const data = await fetch(...);
  4.   return { props: { data } };
  5. }

6. Monitor with Testdom.io

Use Testdom.io to track LCP with mobile/desktop emulation, bandwidth throttling, and full Lighthouse trace:

  1. const { lhr } = await lighthouse(url, options);
  2. console.log('LCP:', lhr.audits['largest-contentful-paint'].displayValue);

With Testdom.io, you get:

  • Real-time and scheduled LCP tests
  • Geo-distributed test nodes
  • Historical trend tracking
  • CI/CD integration and PDF reports

Deliver fast-loading experiences by identifying your true LCP bottlenecks and continuously monitoring performance.