To pass Core Web Vitals on WordPress in 2026, you need LCP under 2.5 seconds, INP under 200ms, and CLS under 0.1 at the 75th percentile of real user visits. Most WordPress sites fail at least one — usually because of missing page cache, render-blocking plugin scripts, or images without explicit dimensions.
This handbook covers the four fixes that move the needle on typical WordPress installs, in the order you should apply them.
Why WordPress Sites Fail Core Web Vitals
WordPress adds layers that static sites do not have: PHP execution on every uncached request, a plugin ecosystem that injects CSS/JS globally, and themes that ship 200KB+ stylesheets. The same Lighthouse audits fail repeatedly:
| Core Web Vital | WordPress root cause | Primary fix |
|---|---|---|
| LCP | No page cache → slow TTFB; unoptimized hero/featured images | WP Rocket + WebP + preload |
| INP | Plugin JS blocking main thread (TBT proxy) | Asset CleanUp + defer scripts |
| CLS | Images/embeds without width/height; ad injection | Explicit dimensions + font-display |
| TTFB | Shared hosting, no object cache, heavy queries | Page cache + Redis object cache |
Run a baseline audit at speedexporter.com or use the WordPress-specific analyzer page. Export the JSON — Lighthouse StackPacks often recommend WP Rocket, Imagify, or Autoptimize when it detects WordPress.
Step 1: Enable Full-Page Caching (Fix TTFB First)
Nothing else matters if your server takes 1.2 seconds to respond. TTFB delays LCP by the same amount — optimizing images cannot compensate for a 900ms server wait.
Recommended setup:- Install WP Rocket (paid) or W3 Total Cache (free) for full-page caching
- Enable GZIP/Brotli compression and browser caching for static assets
- If on managed WordPress (Kinsta, WP Engine, Flywheel), use the host's built-in cache — do not stack two page caches
- Add Redis object cache (via Redis Object Cache plugin) if your host supports it — reduces PHP query time on cache misses
// wp-config.php — enable object cache drop-in when using Redis
define('WP_CACHE', true);
Before/after from a blog with 40 plugins (shared hosting): TTFB 980ms → 180ms after WP Rocket + host CDN. LCP dropped from 3.8s to 2.6s with no other changes.
Step 2: Optimize Images for LCP
WordPress featured images and hero blocks are the LCP element on most posts and pages. Fix them in this order:
Convert to WebP with Imagify or ShortPixel
Both plugins auto-convert uploads and can serve WebP via tags or server rewrite rules. Enable "Optimize on upload" for new media.
Set explicit dimensions
WordPress 6+ adds width and height to block images by default — but classic themes and page builders often omit them. In your theme:
// functions.php — ensure post thumbnails output dimensions
add_filter('wp_get_attachment_image_attributes', function ($attr, $attachment) {
if (empty($attr['width']) || empty($attr['height'])) {
$meta = wp_get_attachment_metadata($attachment->ID);
if ($meta) {
$attr['width'] = $meta['width'];
$attr['height'] = $meta['height'];
}
}
return $attr;
}, 10, 2);
Preload the LCP image
For your homepage hero or single post featured image, add to functions.php:
add_action('wp_head', function () {
if (!is_singular('post')) return;
$thumb_id = get_post_thumbnail_id();
if (!$thumb_id) return;
$url = wp_get_attachment_image_url($thumb_id, 'large');
if ($url) {
printf(
'<link rel="preload" as="image" href="%s" fetchpriority="high">' . "\n",
esc_url($url)
);
}
}, 1);
Never lazy-load the LCP image. Use loading="eager" or omit the attribute on above-the-fold featured images.
Step 3: Stop Plugins Loading Assets Everywhere
This is the single most overlooked WordPress performance fix. Contact Form 7 loading CSS on the homepage. A slider plugin loading 120KB of JavaScript on blog archives. WooCommerce cart fragments on non-shop pages.
Use Asset CleanUp or Perfmatters:- Install Asset CleanUp: Page Speed Booster or Perfmatters
- Visit a page that scores poorly (homepage, archive, single post)
- Open Asset CleanUp's front-end CSS/JS manager (admin bar → Asset CleanUp)
- Unload plugin styles/scripts that are not needed on that URL
- Save and re-run Lighthouse
| Plugin asset | Unload on |
|---|---|
| Contact Form 7 CSS/JS | All pages except /contact |
| WooCommerce cart fragments | Non-shop pages |
| Slider Revolution | Pages without that slider |
| Font Awesome (full pack) | Pages not using icons |
Each unload reduces render-blocking resources and unused JavaScript simultaneously.
Step 4: Fix CLS and INP
CLS: fonts and embeds
Add to your theme CSS or Customizer:
@font-face {
font-family: 'YourBrand';
src: url('/wp-content/themes/yourtheme/fonts/brand.woff2') format('woff2');
font-display: swap;
}
For oEmbed embeds (YouTube, Twitter), use a lazy-load facade plugin or set aspect-ratio on the wrapper:
.wp-block-embed iframe {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
INP: defer non-critical JavaScript
In WP Rocket or your optimization plugin:
- Enable Delay JavaScript execution for analytics, chat widgets, and social embeds
- Exclude jQuery-dependent scripts that break if delayed (test checkout and forms carefully)
- Enable Remove unused CSS only after testing — aggressive CSS removal breaks page builders
Check Lighthouse "Minimize main-thread work" and "Avoid long main-thread tasks" after changes. TBT under 200ms strongly correlates with good INP in the field.
WordPress Core Web Vitals Pass Checklist
| Step | Action | Target metric |
|---|---|---|
| 1 | Full-page cache + CDN | TTFB ≤ 600ms |
| 2 | WebP images + preload featured image | LCP ≤ 2.5s |
| 3 | Asset CleanUp per template | TBT ≤ 200ms |
| 4 | font-display: swap + image dimensions | CLS ≤ 0.1 |
| 5 | Delay JS for third-party widgets | INP ≤ 200ms |
| 6 | Verify in Google Search Console → Core Web Vitals | All green at p75 |
Re-test weekly during changes. GSC field data lags 28 days — lab Lighthouse scores update immediately.
Plugin Stack Recommendation (2026)
There is no single mandatory stack, but this combination resolves most failing audits without conflicts:
| Purpose | Plugin |
|---|---|
| Page cache | WP Rocket or host-native cache |
| Image optimization | Imagify or ShortPixel |
| Asset unloading | Asset CleanUp or Perfmatters |
| Object cache | Redis Object Cache (if host supports Redis) |
| Database cleanup | WP-Optimize (monthly) |
Avoid running two minify/combine plugins simultaneously (WP Rocket + Autoptimize with overlapping features causes broken layouts).
Diagnose Before You Optimize
Export your full Lighthouse JSON and look for these audit IDs:
server-response-time— fix cache firstlargest-contentful-paint-element— identifies your LCP noderender-blocking-resources— lists plugin CSS/JS URLsunused-javascript— often plugin bundleslayout-shift-elements— CLS culprits with impact scores
Feed the JSON to Claude or ChatGPT with your plugin list for tailored unload rules.
Before and After: Magazine Site
| Metric | Before | After |
|---|---|---|
| Performance score (mobile) | 48 | 79 |
| LCP | 4.1s | 2.2s |
| CLS | 0.22 | 0.06 |
| TBT | 1,240ms | 280ms |
Stack: WP Rocket, Imagify, Asset CleanUp with 23 unload rules, font-display: swap. No theme change required.
Further Reading
- WordPress speed audit tool
- How to diagnose slow LCP
- Fix render-blocking resources
- Core Web Vitals glossary
- Use Lighthouse JSON with Claude