← Clarigital·Clarity in Digital Marketing
Technical SEO · Session 2, Guide 1

LCP Optimisation · The Complete Technical Guide

A systematic breakdown of Largest Contentful Paint into its four measurable sub-parts — TTFB, resource load delay, resource load duration, and render delay — with specific, actionable fixes for each phase and real measurement techniques using Chrome DevTools and Search Console.

Technical SEO3,100 wordsUpdated Apr 2026

What You'll Learn

  • The four sub-parts of LCP and how to measure each one independently
  • How to reduce TTFB — the single biggest lever for LCP improvement
  • How to eliminate resource load delay using preload hints and fetchpriority
  • How to reduce resource load duration through image format, compression, and CDN
  • How to eliminate render delay caused by blocking JavaScript and CSS
  • Image-specific optimisation: WebP/AVIF, responsive images, lazy loading errors
  • Font loading strategies that prevent LCP delay
  • How to use Chrome DevTools to diagnose the exact cause of poor LCP

LCP Broken Into Its Four Sub-Parts

Most LCP guidance treats it as a single metric and offers generic advice. Google's official web.dev documentation breaks LCP into four sequential sub-parts, each of which can be independently measured and optimised. Understanding which sub-part is responsible for your poor LCP score is the difference between targeted optimisation and guesswork.

Phase 1

TTFB

Time from navigation start until first byte of HTML received from server

Phase 2

Resource Load Delay

Time from TTFB until browser starts loading the LCP resource

Phase 3

Resource Load Duration

Time to fully download the LCP resource (image, font, etc.)

Phase 4

Render Delay

Time from resource loaded until it is actually painted on screen

The total LCP time is the sum of all four phases. According to Google's analysis of real-world CrUX data, the distribution of LCP time is dominated by different sub-parts for different site types: TTFB is the largest component for server-rendered sites; resource load duration dominates for image-heavy sites with unoptimised assets; render delay is the primary issue for JavaScript-heavy single-page applications.

Measuring sub-parts in Chrome DevTools

Chrome DevTools Performance panel (run a recording) shows all four LCP sub-parts when you click the LCP marker in the timeline. The "Timings" row shows TTFB, FCP, and LCP. Expanding the LCP entry in the "Main" thread shows the breakdown. Alternatively, the web-vitals JavaScript library (web.dev/articles/debug-performance-in-the-field) can report sub-part breakdowns from real user sessions.

Good LCP threshold

2.5s

75th percentile of real page visits must meet this

Largest sub-part (typical)

~40%

TTFB share of total LCP time on average pages

Target TTFB

800ms

Google's recommended maximum TTFB for good LCP

Phase 1: Reducing TTFB

Time to First Byte is the time between the browser's HTTP request for a page and the first byte of the HTML response being received. It is the foundation of LCP — nothing on the page can begin loading until the browser has the HTML. Google recommends a TTFB under 800ms for a good LCP score.

1
Use a Content Delivery Network (CDN)
High Impact

A CDN caches your pages and assets at edge servers geographically close to each user. For most sites, using a CDN is the single highest-impact TTFB improvement available. Without a CDN, every user's request travels to your origin server regardless of distance. With a CDN, cached responses are served from the nearest point of presence.

Implementation: Use CDN providers like Cloudflare, Fastly, Akamai, or AWS CloudFront. Configure full-page caching for static or semi-static pages. Verify Cache-Control headers are set correctly so the CDN retains your pages.

2
Implement Server-Side Caching
High Impact

If your server generates pages dynamically on every request (e.g. querying a database), caching the rendered HTML at the server level means subsequent requests are served from memory rather than re-generated. This can reduce TTFB from 500ms–2s to under 100ms.

Implementation: Page caching plugins for CMS platforms (WP Super Cache, W3 Total Cache for WordPress); Redis or Memcached for application-level caching; full-page caching at the reverse proxy level (Nginx, Varnish).

3
Upgrade Server Resources or Hosting
Medium Impact

Shared hosting with insufficient CPU or memory allocation produces consistently high TTFB under load. Moving to a VPS, dedicated server, or managed cloud hosting is often necessary for sites with significant traffic. Database query optimisation (indexes, query caching) directly reduces dynamic page generation time.

4
Use Early Hints (103 Status Code)
Medium Impact

HTTP 103 Early Hints is a response status that allows the server to send Link: rel=preload headers before the full 200 response is ready. This enables the browser to begin fetching critical resources (fonts, CSS, the LCP image) while the server is still generating the main response — effectively running Phase 2 in parallel with Phase 1.

Chrome has supported Early Hints since version 103. Server support requires configuration at the CDN or web server level — Cloudflare, Apache, and Nginx all support Early Hints.

Phase 2: Eliminating Resource Load Delay

Resource load delay is the time between the first byte of HTML being received and when the browser actually starts downloading the LCP resource. The ideal value is zero — the LCP resource should begin downloading as early as possible. Any delay here means the browser discovered the LCP resource later than necessary.

1
Preload the LCP Resource
High Impact

If the LCP element is an image (the most common case), add a <link rel="preload"> hint in the <head> of your HTML. This tells the browser to fetch the resource immediately during HTML parsing, before it has built the DOM or render tree.

<link rel="preload" 
      href="/images/hero.webp" 
      as="image" 
      fetchpriority="high">

For responsive images that vary by screen size, use the imagesrcset and imagesizes attributes on the preload link:

<link rel="preload" 
      as="image"
      href="/images/hero-1200.webp"
      imagesrcset="/images/hero-640.webp 640w, /images/hero-1200.webp 1200w"
      imagesizes="100vw"
      fetchpriority="high">
2
Add fetchpriority="high" to the LCP Image Element
High Impact

The fetchpriority attribute on <img> elements signals to the browser that this resource should be fetched at highest priority. Without it, the browser may deprioritise hero images relative to scripts and stylesheets.

<img src="/images/hero.webp" 
     alt="Hero image"
     width="1200" 
     height="600"
     fetchpriority="high">

Critical: Only add fetchpriority="high" to the LCP image. Adding it to multiple images defeats the purpose — the browser can only prioritise one resource. Adding it to non-LCP images will actually hurt LCP by diverting bandwidth.

3
Avoid Lazy Loading the LCP Image
High Impact

loading="lazy" on the LCP image is one of the most common and impactful LCP mistakes. Lazy loading defers image loading until the user scrolls near the image — for the LCP element, which is above the fold, this delay is unnecessary and directly adds to LCP time.

Only use loading="lazy" on images that are below the fold. The LCP image, hero images, and any above-the-fold images should either have loading="eager" (the default) or no loading attribute at all.

Phase 4: Eliminating Render Delay

Render delay is time lost between the LCP resource finishing its download and the browser actually painting it on screen. The ideal render delay is zero. Common causes include render-blocking CSS and JavaScript that prevent the browser from painting even after resources are available, and client-side rendering frameworks that require JavaScript execution before any content appears.

1
Eliminate Render-Blocking Resources
High Impact

CSS stylesheets in the <head> are render-blocking by default — the browser pauses rendering until all CSS is downloaded and parsed. JavaScript files with no async or defer attribute in the <head> are also render-blocking.

For CSS: Inline critical CSS (the styles needed to render above-the-fold content) directly in the <head>. Load the full stylesheet with media="print" and switch it back to all after load (a common pattern for non-critical CSS deferral):

<!-- Critical CSS inline -->
<style>/* above-fold styles here */</style>

<!-- Non-critical CSS deferred -->
<link rel="stylesheet" href="/styles.css" 
      media="print" onload="this.media='all'">

For JavaScript: Add defer to all non-critical scripts. Use async only for truly independent scripts (analytics, ads). Move scripts to the end of <body> if refactoring is not possible.

2
Avoid Client-Side Rendering for Above-Fold Content
High Impact

Single-page applications (React, Vue, Angular) that render content entirely on the client side have render delay as a structural problem — the LCP element cannot paint until JavaScript downloads, parses, and executes. This often adds 1–3 seconds of render delay.

Solutions: Server-side rendering (SSR) or static site generation (SSG) ensures the HTML delivered to the browser already contains the content. Streaming SSR (React 18+) sends HTML progressively, reducing TTFB and enabling earlier LCP. Partial hydration strategies can reduce JavaScript execution time for above-fold content.

Phase 3: Image Optimisation for LCP

When the LCP element is an image (the most common case — hero images, featured images, product images), resource load duration is determined by the image file size and the user's available bandwidth. Reducing file size without visible quality loss is the primary lever.

1
Convert to WebP or AVIF Format
High Impact

WebP provides 25–35% smaller file sizes than JPEG at equivalent visual quality. AVIF (AV1 Image Format) provides 50%+ reduction compared to JPEG, though encoding is slower and browser support, while now broad, is slightly less universal than WebP. Use the <picture> element with a JPEG fallback for maximum compatibility:

<picture>
  <source srcset="/hero.avif" type="image/avif">
  <source srcset="/hero.webp" type="image/webp">
  <img src="/hero.jpg" alt="Hero" 
       width="1200" height="600" fetchpriority="high">
</picture>
2
Size Images Correctly for the Viewport
High Impact

Serving a 3000×2000px image for a hero that displays at 800×533px on desktop (and smaller on mobile) wastes significant bandwidth. Use responsive images with srcset and sizes to serve appropriately sized images for each viewport:

<img 
  srcset="/hero-640.webp 640w, /hero-1024.webp 1024w, /hero-1600.webp 1600w"
  sizes="(max-width: 768px) 100vw, 1200px"
  src="/hero-1600.webp"
  alt="Hero"
  width="1600" height="900"
  fetchpriority="high">

This ensures mobile users on 360px-wide screens download a ~360px image rather than a 1600px image — a 20x file size reduction.

3
Set Explicit Width and Height Attributes
Medium Impact

Width and height attributes prevent layout shifts (CLS) and allow the browser to allocate space for the image before it loads — enabling painting to begin sooner. Always add explicit width and height matching the image's intrinsic dimensions. Use CSS to make the image responsive, not the HTML attributes:

img { max-width: 100%; height: auto; }
Background images via CSS are late-discovered

If your LCP element is a CSS background image (set via background-image: url()), the browser cannot discover and begin downloading it during initial HTML parsing — it must parse the CSS first. This adds significant resource load delay. Where possible, use an <img> element instead of a CSS background for the LCP image. If you must use a CSS background, add a <link rel="preload" as="image"> hint for it in the <head>.

Font Loading and LCP

When the LCP element is a text block (the second most common case — large headings, hero text), web font loading becomes a critical LCP factor. If the LCP text renders using a web font that loads late, the text is invisible until the font arrives — directly adding to LCP time.

1
Preload Critical Web Fonts
High Impact

Add a preload hint for the font used in the LCP text element. Specify crossorigin (required for fonts even from the same origin):

<link rel="preload" 
      href="/fonts/Inter-Bold.woff2" 
      as="font" 
      type="font/woff2" 
      crossorigin>
2
Use font-display: optional or swap
Medium Impact

font-display: optional prevents any font-related render delay — if the font is not available in cache, the browser uses a fallback immediately without waiting. This eliminates font-related LCP delay but means some users see a fallback font on first visit. font-display: swap shows fallback text immediately and swaps to the web font when it loads — this can cause CLS if the font metrics differ significantly from the fallback.

For LCP text elements, font-display: optional combined with font preloading is the most LCP-friendly configuration: returning visitors (with the font cached) get the intended font with no delay; first visitors get immediate text rendering with a system font.

Self-hosting fonts beats Google Fonts for LCP

Fonts loaded from Google Fonts (fonts.googleapis.com) require a cross-origin connection — an additional DNS lookup, TCP connection, and TLS handshake before the font download can begin. Self-hosting fonts on your own domain eliminates this cross-origin overhead. For LCP-critical fonts, self-hosting with a preload hint is consistently faster than Google Fonts.

Third-Party Scripts and LCP

Third-party scripts — analytics platforms, chat widgets, ad networks, tag managers, social embeds — are among the most common causes of poor real-world LCP. They consume bandwidth and main thread time, directly competing with the LCP resource for loading and rendering priority.

How third-party scripts harm LCP

  • Bandwidth competition. HTTP/2 multiplexing allows parallel connections, but bandwidth is still finite. Multiple third-party scripts downloading simultaneously compete with the LCP resource.
  • Main thread blocking. JavaScript execution is single-threaded. Any synchronous third-party script in <head> blocks parsing and rendering until it executes.
  • Render-blocking. Third-party CSS loaded via <link rel="stylesheet"> blocks rendering in the same way as first-party CSS.
  • DNS and connection latency. Each unique third-party domain requires a new DNS lookup and connection. Preconnecting to critical third-party origins helps: <link rel="preconnect" href="https://analytics.example.com">.

Audit and reduce third-party impact

Use Chrome DevTools Network panel with the "Third-party" filter. Sort by size and duration to identify the most expensive third-party requests. Consider: removing scripts that are not business-critical, loading non-critical scripts after the page becomes interactive (using a facade pattern for chat widgets, loading analytics after user interaction), and using Google Tag Manager's trigger configuration to fire tags only when needed rather than on every page view.

Measuring and Debugging LCP

ToolData TypeBest For
Google Search Console — Core Web VitalsField (CrUX)Understanding real user LCP distribution; identifying worst-performing page groups
PageSpeed InsightsField + LabPer-URL diagnosis; combines real data with diagnostic recommendations
Chrome DevTools — PerformanceLabIdentifying the exact LCP element and which sub-part is largest
WebPageTestLabWaterfall analysis; testing from multiple locations; filmstrip view showing when LCP element paints
Lighthouse (CLI/DevTools)LabAutomated recommendations; CI/CD integration for regression prevention
web-vitals JS libraryField (custom)Collecting LCP sub-part breakdowns from real users in your own analytics

Diagnosing LCP in Chrome DevTools step-by-step

  1. Open Chrome DevTools → Performance tab
  2. Check "Screenshots" and optionally "Web Vitals"
  3. Click the circular Record button, then reload the page
  4. Stop recording after the page fully loads
  5. In the Timings row, find the "LCP" marker — click it
  6. The panel below shows which element was the LCP element and its timestamp
  7. Examine the waterfall to find that element's resource request — identify when it was requested, when it started downloading, and when it finished
  8. The gap between navigation start and the request start = TTFB + resource load delay
  9. The download bar length = resource load duration
  10. The gap between download end and the LCP timestamp = render delay

Authentic Sources

OfficialGoogle web.dev — Optimise LCP

Official LCP optimisation guide including the four sub-part framework.

OfficialGoogle web.dev — Largest Contentful Paint

Official LCP definition, eligible elements, and threshold values.

OfficialGoogle web.dev — Optimise Resource Loading with fetchpriority

Official documentation on the fetchpriority attribute and its impact on LCP.

OfficialGoogle web.dev — Preload Responsive Images

Official guidance on using preload with imagesrcset for responsive LCP images.

OfficialChrome Developers — Early Hints

Official documentation on HTTP 103 Early Hints and its impact on TTFB and LCP.

OfficialGoogle web.dev — Web Font Best Practices

Official guidance on font loading strategies and their impact on LCP and CLS.

600 guides on digital marketing. All authentic sources.

Official documentation, academic research, and government data only.