LCP (Largest Contentful Paint) is the moment the user feels the page has “loaded”. Hero image, main heading, featured video poster: usually the largest visible element on the page.
It’s the SEO-sensitive metric in Google’s Core Web Vitals. You want under 2.5 seconds. Above 4 seconds is “poor” and drags ranking down.
I’ve been tuning WordPress performance for 15+ years. Here’s the 10-point checklist I run when I’m improving LCP.
1. Identify the LCP element
Every site has a different one. Chrome DevTools Lighthouse or the Performance tab will highlight the LCP element for you.
Most common LCP elements:
– Hero image (product or landing page)
– Featured blog post image
– H1 heading (minimal design sites)
– Video poster image
– Above-the-fold large text
Knowing the LCP element is what focuses your optimization work. Everything else is fluff.
2. Load the hero image eagerly
The most common mistake: WordPress puts the lazy-load attribute on the hero image too. That image is in the initial viewport and should not be lazy loaded.
Fix in the theme:
// Disable lazy load for the hero image
add_filter('wp_get_attachment_image_attributes', function($attr, $attachment) {
if (is_hero_image($attachment)) {
$attr['loading'] = 'eager';
$attr['fetchpriority'] = 'high';
}
return $attr;
}, 10, 2);fetchpriority="high" tells the browser “this image matters”. Modern browsers honour it.
3. Modernise image format
JPEG to WebP: 25 to 35% smaller.
WebP to AVIF: another 20 to 30%.
WordPress setup:
– ShortPixel or Imagify auto-convert
– Native WebP support from WordPress 5.8+
– AVIF is not yet native, you need a plugin
On a test site I moved the hero from a 250KB JPEG to a 110KB WebP. LCP went from 1.2s to 0.8s.
4. Specify image dimensions
Without dimensions the browser can’t allocate space before the image loads, which means layout shift.
HTML:
<img src="hero.webp" width="800" height="400" alt="..." fetchpriority="high">Responsive:
img {
width: 100%;
height: auto;
aspect-ratio: 2 / 1; /* prevents layout shift */
}The aspect-ratio CSS property reserves space even before real image dimensions are known.
5. Responsive images (srcset)
Sending a 4K image to a mobile device is wasted bandwidth.
<img src="hero-800.webp"
srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1600.webp 1600w"
sizes="(max-width: 600px) 400px, (max-width: 1200px) 800px, 1600px"
alt="...">The browser picks the best image for the device and viewport.
In WordPress wp_get_attachment_image() generates srcset automatically. On a custom theme you write it yourself.
6. Preload the LCP image
While parsing HTML the browser prioritises CSS and JS. Aggressive image download doesn’t start until the image is in the DOM.
<link rel="preload"> kicks the image off early:
<link rel="preload"
as="image"
href="hero.webp"
imagesrcset="hero-400.webp 400w, hero-800.webp 800w"
imagesizes="(max-width: 600px) 400px, 800px"
fetchpriority="high">The image starts downloading before it even appears in the HTML. 200 to 500ms shaved off LCP.
7. Improve server-side TTFB
LCP depends on TTFB. If the server doesn’t answer, the browser can’t render anything.
TTFB targets:
– Under 200ms: excellent
– Under 500ms: good
– Under 800ms: OK
– Over 1s: problem
TTFB optimization is its own topic (another post). Summary: caching layer (page cache plus object cache), database optimization, PHP OPcache, lightweight theme.
8. Inline critical CSS
The browser can’t render until the external CSS file loads. That’s “render-blocking CSS”.
Solution: critical CSS. Above-the-fold styles go inline in a <style> block in the HTML. The rest loads async.
<style>
/* Critical above-the-fold CSS */
.hero { ... }
.nav { ... }
.heading { ... }
</style>
<link rel="preload" href="/style.css" as="style" onload="this.rel='stylesheet'">WordPress plugins like Autoptimize and WP Rocket automate this.
9. Optimise font loading
If the LCP element is a heading styled in a custom font, font loading is on the critical path.
font-display: swap
@font-face{
font-family: 'Custom';
src: url('/fonts/custom.woff2') format('woff2');
font-display: swap;
}swap means the fallback font shows immediately and swaps in the custom font once it loads. The LCP element can render with the fallback.
Preload the critical font:
<link rel="preload" href="/fonts/custom.woff2" as="font" type="font/woff2" crossorigin>Minimise font weights: use two weights instead of three. A single variable font file.
10. Minimise and defer JavaScript
JS parse and execute block the main thread. CSS work gets delayed and LCP slips.
Strategies:
1. Defer non-critical scripts:
<script src="/analytics.js" defer></script>
<script src="/chat-widget.js" defer></script>2. Async for independent scripts:
<script src="/ad-tag.js" async></script>3. Remove unused JavaScript. Lighthouse’s “unused JavaScript” report will tell you what to dequeue from plugins.
4. Code splitting. Route-based splits so the initial load is small.
5. Lazy-load third-party. Chat widgets and analytics only after a user interaction.
Bonus: use a CDN
A CDN serves static assets from close to the user. Latency drops dramatically.
Popular CDNs:
– Cloudflare (free tier is good enough)
– BunnyCDN ($1 a month, simple pricing)
– Fastly (enterprise)
– AWS CloudFront
WordPress setup is a 10-minute job. For a global audience LCP improves 30%+.
Monitoring
How I track LCP:
Synthetic (lab data):
– Lighthouse (single run)
– PageSpeed Insights
– WebPageTest (multiple runs, real locations)
Real User Monitoring (RUM):
– Google Search Console Core Web Vitals report
– web-vitals.js library
– Custom backend logging
Weekly check on the LCP p75 metric (the real user experience).
A before and after
One client project’s optimization journey:
Baseline:
– LCP: 4.2s (poor)
– LCP element: hero product image (450KB JPEG)
Actions:
1. WebP convert: 450KB, then 180KB
2. fetchpriority high plus preload
3. Responsive srcset
4. Hero font preload
5. Deferred render-blocking scripts
Result:
– LCP: 1.4s (good)
– Improvement: 2.8s (67% faster)
Total work: one week. SEO ranking gained two positions, organic traffic went up 18%.
Takeaway
LCP improvement is systematic. Identify the LCP element, optimise images, preload, minimise render-blocking.
This 10-point checklist applies to most sites. A focused week of work can knock 2 to 3 seconds off LCP.
Monitoring is an ongoing discipline. Regressions creep in as content is added or plugins update. Periodic Lighthouse checks are part of the job.