LCP (Largest Contentful Paint) is the most difficult Core Web Vital to optimize because it depends on several chained factors: server speed, network efficiency, resource size and format, and rendering prioritization. This guide breaks the problem down into its root causes and provides concrete solutions for each one.
How LCP is calculated exactly
Google divides LCP time into four cumulative phases: time to first byte from the server (TTFB), LCP resource load delay, resource load duration, and element render delay. Identifying which of these phases consumes the most time is the first step of the diagnosis.
| Phase | What it measures | Target |
|---|---|---|
| TTFB | Time to receive the first byte of the HTML | < 800 ms |
| Resource load delay | Time between TTFB and start of LCP resource loading | < 200 ms |
| Resource load duration | Download time of the LCP resource (image, etc.) | < 500 ms |
| Element render delay | Time between end of download and visible rendering | < 200 ms |
Cause 1: Slow server (high TTFB)
If the server takes more than 800ms to return the first byte of HTML, the LCP is already delayed before the browser has downloaded anything. This is the most common cause on sites with low-quality hosting, poorly optimized databases, or no page caching.
- •Enable full-page caching (in WordPress: WP Rocket, W3 Total Cache; in Next.js: ISR or CDN caching).
- •Use a CDN (Cloudflare, Vercel Edge, Fastly) to serve HTML from servers close to the user.
- •Optimize the slowest database queries — use MySQL's slow query log or your CMS debug panel.
- •Consider more powerful or serverless hosting if the current server is consistently overloaded.
Cause 2: LCP image without preload or optimization
The LCP element is usually a hero image or main banner. If that image is not preloaded, the browser will not download it until it parses the HTML and encounters the <img> tag — adding significant delay.
<!-- Add this preload in the <head> for the LCP image -->
<link rel="preload" as="image" href="/images/hero.webp"
imagesrcset="/images/hero-480.webp 480w, /images/hero-1024.webp 1024w"
imagesizes="100vw" fetchpriority="high" />
<!-- The corresponding <img> tag must have fetchpriority="high" -->
<img src="/images/hero.webp"
srcset="/images/hero-480.webp 480w, /images/hero-1024.webp 1024w"
sizes="100vw"
fetchpriority="high"
alt="Site hero" />- •Convert images to WebP or AVIF format — typical size reduction of 30–50% without visible quality loss.
- •Resize images to the maximum size they are displayed — do not serve a 4000px image for a 1200px element.
- •Add loading="eager" (or remove loading="lazy") on the LCP image — lazy loading delays loading of the most important element.
Cause 3: Render-blocking CSS or JavaScript
The browser cannot render anything until it has processed all synchronous CSS and JavaScript in the <head>. Every external CSS or JS file you add to the <head> without async or defer blocks rendering and delays LCP.
<!-- Incorrect: blocks rendering -->
<script src="/app.js"></script>
<link rel="stylesheet" href="/non-critical.css">
<!-- Correct: JS with defer, non-critical CSS with preload + onload -->
<script src="/app.js" defer></script>
<link rel="preload" href="/non-critical.css" as="style"
onload="this.rel='stylesheet'">- •Inline critical (above-the-fold) CSS directly in the <head> to eliminate the network round-trip.
- •Load remaining CSS asynchronously with the preload + onload technique.
- •Use defer or async on all <head> scripts that are not critical for the initial render.
- •Identify and remove non-essential third-party scripts from the <head> (social widgets, chats, non-critical analytics).
Cause 4: Web fonts blocking text
If the LCP element is a text block using a custom web font, the browser may display invisible text (FOIT) or text with the fallback font (FOUT) until the font loads. This delays LCP because Google measures it when the element is visible with its final content.
/* Add font-display: swap or optional to prevent invisible text */
@font-face {
font-family: 'MyFont';
src: url('/fonts/my-font.woff2') format('woff2');
font-display: swap; /* Shows fallback immediately, substitutes on load */
}- •Preload the most important fonts with <link rel="preload" as="font">.
- •Use font-display: optional if the font is not critical — the browser only uses it if already cached.
- •Host fonts on your own server instead of Google Fonts to avoid the extra DNS resolution.
- •Limit the number of font variants (weights/styles) you load to only those strictly needed.
Cause 5: LCP element using a CSS background-image
If the LCP element uses background-image in CSS instead of an <img> tag, the browser cannot preload that image — it must first download the CSS, parse it, and apply it to know there is a background image. This adds significant delay.
- •Whenever possible, use <img> or <picture> tags for main images — they support native preload, srcset, and lazy loading.
- •If you need to keep background-image for design reasons, preload the image manually with <link rel="preload">.
- •Make sure the CSS defining the background-image is inlined critical CSS, not an external file.
Diagnose your exact cause
iRankly's Core Web Vitals Monitor shows you the current LCP for each URL and prioritized optimization suggestions from PageSpeed Insights. Use it to identify which URLs have LCP in the "Needs improvement" or "Poor" range and prioritize which to optimize first.
Prueba la herramienta gratis
Core Web Vitals MonitorAnaliza tus URLs con {tool} de iRankly. Sin registro, sin tarjeta.
For a more detailed analysis of LCP phases, use WebPageTest (webpagetest.org) with the "LCP Breakdown" option enabled. It shows exactly how much time each LCP phase consumes and where the main bottleneck is.