Skip to content
Back to Blog
Performance8 min read

Core Web Vitals Optimization: 7 Fixes for LCP Under 2.5s

Largest Contentful Paint kills PageSpeed scores when hero images load slowly. Here's how to fix image delivery, eliminate render blocking, and cut server response time.

Written by Abdul AbrorTechnical Hosting Support Engineer
Core Web Vitals Optimization: 7 Fixes for LCP Under 2.5s
On this page

Google's Largest Contentful Paint metric measures how fast your biggest visible element loads—usually a hero image, banner, or text block. Sites that hit 2.5 seconds or better pass. Most don't.

I've walked dozens of clients through LCP fixes in support tickets. The usual suspects are oversized images, blocking CSS and JavaScript, and slow Time to First Byte. Once you isolate which layer is the bottleneck, the fix is straightforward.

Why LCP matters for hosting clients

LCP is one of three Core Web Vitals that Google uses in search ranking. A slow score above 4 seconds lands you in the "poor" bucket and can cost you organic visibility. For hosting environments—shared cPanel accounts, VPS, managed WordPress—you often inherit server-layer constraints that inflate LCP even when your code is clean.

PageSpeed Insights and Lighthouse break down where the delay happens. Look at the filmstrip timeline first. If your hero image appears late, you'll see a blank viewport for two or three seconds. That's LCP.

What actually slows down LCP

Three factors dominate:

  1. Image size and format – a 3 MB JPEG takes time to download, decode, and paint.
  2. Render-blocking resources – CSS and JS files that stop the browser from displaying content until they finish loading.
  3. Server response time – if TTFB sits above 600 ms, every downstream metric suffers.

Fix these in order. You can shrink an image in five minutes; optimizing TTFB might mean upgrading your hosting plan or tuning PHP-FPM.

Step 1: optimize your LCP image

Start with the image itself. Right-click in Chrome DevTools, inspect the element Lighthouse flags, and note its dimensions and file size. If you're serving a 2400×1600 PNG when the rendered size is 800×533, you're wasting bandwidth.

Resize to display dimensions. Export at 2× the CSS width for Retina screens. An 800 px wide slot needs a 1600 px source image, not 2400 px.

Switch to modern formats. WebP cuts file size by 25–35% versus JPEG at the same visual quality. AVIF goes further but browser support in older Safari lags. Serve WebP with a JPEG fallback:

<picture>
  <source srcset="hero.webp" type="image/webp">
  <img src="hero.jpg" alt="Hero image" width="800" height="533">
</picture>

Compress aggressively. Tools like ImageOptim, Squoosh, or cwebp can drop a 500 KB JPEG to 150 KB without visible loss. For WordPress, plugins like ShortPixel or EWWW run batch compression on upload.

Set explicit width and height. The browser reserves layout space immediately, preventing Cumulative Layout Shift and letting the paint happen as soon as bytes arrive.

In my experience, image resizing alone often shaves a full second off LCP. It's the highest-ROI fix.

Step 2: preload the LCP resource

Once the image is optimized, tell the browser to fetch it early. Add a <link rel="preload"> in your <head>:

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

Preload elevates the image's fetch priority so the browser requests it before parsing the full HTML. For hero images above the fold, this cuts discovery time by 200–400 ms.

Don't preload more than one or two critical images. Too many preload hints compete for bandwidth and dilute the benefit.

Step 3: eliminate render-blocking CSS

CSS blocks rendering by default. The browser waits for every stylesheet to download and parse before painting the page. If you're loading five external stylesheets—framework, theme, plugins, custom—each round trip adds delay.

Inline critical CSS. Extract the styles needed for above-the-fold content and drop them in a <style> tag in the <head>. Tools like Critical or Penthouse automate extraction. Load the rest asynchronously:

<link rel="preload" href="/css/main.css" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="/css/main.css"></noscript>

Concatenate and minify. Merge multiple CSS files into one, strip whitespace, and serve it from a CDN. Fewer requests mean fewer TLS handshakes and faster paint.

For WordPress, plugins like Autoptimize or WP Rocket handle concatenation and async loading. Check your theme's settings too; some bundle an option to inline critical styles.

Step 4: defer or async non-critical JavaScript

JavaScript blocks HTML parsing unless you mark it defer or async. Both attributes let the browser continue building the DOM while the script downloads, but defer waits until parsing finishes and async executes immediately.

Use defer for scripts that manipulate the page:

<script src="/js/app.js" defer></script>

Use async for analytics and third-party widgets that don't touch the DOM directly:

<script src="https://www.googletagmanager.com/gtag/js" async></script>

Move scripts to the footer. If you control the HTML, place <script> tags before the closing </body>. The browser paints the page before downloading JS.

Remove unused scripts. Audit your site with Coverage in Chrome DevTools. If a plugin loads 80 KB of JavaScript on every page but only runs on the contact form, disable it globally and enqueue conditionally.

So what if you've inlined CSS, deferred JS, and optimized images but LCP is still slow?

Step 5: reduce server response time (TTFB)

Time to First Byte measures how long the server takes to respond after the browser sends a request. If TTFB exceeds 600 ms, everything downstream—LCP, FCP, Speed Index—suffers.

Enable caching. Static HTML served from disk or memory is 10× faster than dynamically generated PHP. For WordPress, install a page cache plugin like WP Super Cache or LiteSpeed Cache. For cPanel shared hosting, check if Varnish or Redis is available and enable it.

Upgrade PHP. PHP 7.4 and 8.x are substantially faster than 5.6 or 7.0. Log in to cPanel, navigate to Select PHP Version, and pick the newest your plugins support. Test staging first.

Use a CDN. Cloudflare, BunnyCDN, or KeyCDN serve static assets from edge servers close to your visitors. CDN latency is typically 20–50 ms versus 200–400 ms for a distant origin. Cloudflare's free tier caches images, CSS, and JS automatically.

Check server resource usage. Run top or htop on a VPS to see if CPU or memory is maxed. If PHP-FPM or MySQL is the bottleneck, tune pm.max_children, increase RAM, or move to a larger plan. On shared hosting, a resource limit might throttle your site during traffic spikes—contact support to review usage logs.

Optimize database queries. Slow queries inflate TTFB. Install Query Monitor for WordPress, identify slow SQL, and add indexes or refactor the code. For WooCommerce or membership sites, database bloat from transients and postmeta can kill performance—run WP-Optimize to clean cruft.

In tickets I handled, raising PHP-FPM worker limits and enabling Redis dropped TTFB from 1.2 s to under 300 ms. Server-side fixes have compounding effects on every metric.

Step 6: lazy-load off-screen images

Images below the fold don't need to block LCP. Lazy-loading defers their download until the user scrolls near them, freeing bandwidth for critical resources.

Native lazy-loading is built into modern browsers:

<img src="gallery-photo.jpg" loading="lazy" alt="Gallery photo">

For older browsers, libraries like lazysizes add a polyfill. WordPress has native lazy-loading since version 5.5; it applies automatically to content images.

Don't lazy-load the LCP image. If you mark your hero image loading="lazy", the browser delays fetching it and LCP worsens. Only lazy-load content below 600–800 px from the top.

Step 7: measure and iterate

After each fix, re-run Lighthouse or PageSpeed Insights. LCP can shift if a different element becomes the largest—maybe the hero image is fast now but an H1 text block paints late because of a web font.

Test on a real device over a throttled connection. Lighthouse mobile uses a simulated slow 4G profile; your real users might be on worse networks. Chrome DevTools → Network → Throttling → Slow 3G gives you a baseline.

Check field data in Google Search Console under Core Web Vitals. Lab scores (Lighthouse) predict potential; field data (CrUX) reflects actual user experience over the past 28 days. Aim for 75% of visits under 2.5 s.

Quick wins for common platforms

WordPress

  • Install a caching plugin and enable page cache, browser cache, and object cache.
  • Use a lightweight theme (GeneratePress, Astra) instead of page builders.
  • Limit plugins; deactivate any you don't need.
  • Enable lazy-loading and serve WebP via Imagify or ShortPixel.

cPanel shared hosting

  • Enable LiteSpeed or Varnish if your host supports it.
  • Turn on Cloudflare under Domains → Zone Editor for free CDN.
  • Upgrade PHP to 8.0 or newer.
  • Check resource usage in Metrics → Resource Usage; if you're hitting limits, consider VPS.

Static sites

  • Serve WebP and set correct Cache-Control headers.
  • Use a CDN (Cloudflare, Netlify, Vercel).
  • Inline critical CSS for above-the-fold content.
  • Preload fonts and LCP images.

VPS or dedicated

  • Tune PHP-FPM: set pm.max_children based on available RAM.
  • Install Redis or Memcached for object caching.
  • Enable HTTP/2 or HTTP/3 in your web server config.
  • Use Gzip or Brotli compression for text assets.

What to check first

If LCP is above 2.5 s, start with the image: resize, compress, convert to WebP, and preload. That single fix often drops LCP by a full second.

Next, audit render-blocking CSS and JS. Inline critical styles, defer scripts, and move non-essential code to the footer. Check TTFB; anything over 600 ms needs server-side attention—enable caching, upgrade PHP, or move to faster hosting.

Measure after each change. Field data from real users is the final arbiter, not lab scores. Once 75% of visits hit 2.5 s, you're in the green.

FAQ

What is a good LCP score?

Under 2.5 seconds is good, 2.5–4.0 s needs improvement, above 4.0 s is poor. Aim for under 2.5 s for 75% of page loads.

Does hosting affect LCP?

Yes. Shared hosting with slow TTFB, limited PHP workers, or no caching inflates LCP. A fast VPS or managed WordPress host with Redis and CDN integration makes a measurable difference.

Should I optimize every image or just the LCP image?

Prioritize the LCP image first—it has the biggest impact. Then lazy-load and compress below-the-fold images to reduce overall page weight and improve other metrics.

Can a CDN alone fix LCP?

A CDN speeds up asset delivery and cuts TTFB for cached resources, but it won't fix a 5 MB uncompressed image or render-blocking CSS. Combine CDN with image optimization and async loading.

How do I find which element is my LCP?

Run Lighthouse in Chrome DevTools. The report shows the LCP element with a screenshot and highlights it in the filmstrip. Inspect it to see tag, file path, and size.