LCP should be under 2.5 seconds on mobile. Five fixes that work for 90% of sites: (1) optimize and preload your hero image, (2) eliminate render-blocking resources above the fold, (3) use a CDN, (4) enable HTTP/2 or HTTP/3, (5) reduce server response time (TTFB) under 600ms.
LCP (Largest Contentful Paint) measures when the biggest visible element on your page finishes rendering. Usually a hero image, sometimes a large headline. It's the most-failed Core Web Vital on mobile.
**LCP thresholds (mobile field data):**
- **Good:** under 2.5 seconds - **Needs improvement:** 2.5s–4.0s - **Poor:** over 4.0 seconds
**Step 1: identify what your LCP element actually is.**
Most sites assume their LCP is the hero image. Often it's actually:
- A large headline (text LCP) - A poster frame for an embedded video - A background image set via CSS (counts as LCP if visible above fold) - A logo (if your site is mostly text and the logo is the largest visible element)
Use Chrome DevTools > Performance > LCP marker, or PageSpeed Insights' "Largest Contentful Paint element" report, to see exactly which element Google measured.
**Step 2: apply fixes specific to the element type.**
**For image LCP (most common):**
- **Serve in modern formats** — WebP or AVIF. AVIF typically saves another 30–50% over WebP at equivalent quality. - **Right-size the image** — never serve a 4000px-wide image to mobile screens. Use `<picture>` with srcset and sizes attributes. - **Preload the LCP image** — `<link rel="preload" as="image" href="...">` in your `<head>`. This tells the browser to fetch the LCP image before discovering it via HTML parsing. - **Avoid lazy-loading the LCP image.** Lazy loading defers the image fetch, which delays LCP. Only lazy-load images below the fold. - **Use `fetchpriority="high"` on the LCP image element** — modern browser hint that explicitly prioritizes this image.
**For text LCP:**
- **Avoid web fonts on the LCP text.** Or use `font-display: optional` to prevent FOUT/FOIT delays. - **If you must use a custom font, preload it** — `<link rel="preload" as="font" type="font/woff2" href="..." crossorigin>`. - **Use `size-adjust` and `ascent-override` CSS properties** for fallback fonts to match custom font metrics — eliminates layout shift when font swaps in.
**For background-image LCP:**
- **Inline a base64 placeholder** (small, blurred version) so the area renders immediately - **Preload the full image** as you would for an `<img>` LCP - **Consider replacing with an `<img>` element** — easier to optimize and preload
**Step 3: fix the underlying delivery infrastructure.**
**Server response time (TTFB) under 600ms:**
If your TTFB is over 1 second, no front-end optimization will save you. Common causes:
- Slow CMS (especially WordPress without caching) - No CDN — every request hits your origin server - Unoptimized database queries - Geographic distance from users
**Fix:** add a CDN (Cloudflare, BunnyCDN, Fastly). Enable HTTP/2 or HTTP/3. Move your origin closer to your audience (Canadian audiences = Canadian or US East regions).
**Render-blocking resources above the fold:**
Synchronous CSS and JavaScript in your `<head>` blocks rendering until they're loaded and parsed. Common offenders:
- Massive global stylesheets (loading 800KB of CSS for a 50KB page) - Synchronous Google Fonts - Synchronous third-party scripts (analytics, chat, etc.)
**Fix:** inline critical CSS in your `<head>` (under 14KB ideally). Defer non-critical CSS via `media="print" onload="this.media='all'"` trick. Async/defer all non-critical JavaScript.
**The honest assessment:**
Most LCP failures come from one of three patterns:
1. **A 2MB hero image served at full size to mobile devices.** The single most-common LCP killer. Fix this and 50% of sites pass LCP immediately. 2. **A 6MB JavaScript bundle blocking initial render.** Common in SPAs without code-splitting. 3. **No CDN, slow shared hosting, and poor caching.** Common in low-end WordPress hosting.
If you address these three things, you'll fix LCP for the vast majority of sites without touching anything else.
- **What is INP and how do I fix poor INP scores?** — Interaction to Next Paint — measures how quickly your page responds to user input. Should be under 200ms (good) or under 500ms (acceptable). Replaced FID in March 2024. Most pages with poor INP have heavy JavaScript event handlers or excessive third-party scripts blocking the main thread. - **What's a good Core Web Vitals score in 2026?** — All three metrics in the 'Good' threshold (LCP <2.5s, INP <200ms, CLS <0.1) at the 75th percentile of mobile users over the trailing 28 days. About 40% of websites achieve this in 2026 — passing all three is a meaningful competitive edge. - **Lab vs field data — which one does Google actually use?** — Field data (real user measurements) is what Google uses for ranking. Lab data (synthetic Lighthouse runs) is for debugging only. A site can have perfect Lighthouse scores and still fail Core Web Vitals if real users experience poor performance. - **Why does my React/Vue/Angular SPA have poor Core Web Vitals?** — SPAs ship large JavaScript bundles that block the main thread during hydration. The browser must download, parse, compile, and execute the bundle before the page becomes interactive. Solutions: code-splitting, server-side rendering, partial hydration, or migrating to a meta-framework (Next.js, Nuxt, Remix, Astro).