Written by 2:55 am How To, WordPress Views: 5

WordPress Core Web Vitals: Fix LCP, CLS, and INP

Fix WordPress Core Web Vitals with developer-level techniques: fetchpriority and preload for LCP, intrinsic sizing and font-display for CLS, main-thread yielding and script deferral for INP.

WordPress Core Web Vitals - Fix LCP, CLS, and INP — Developer Guide

Core Web Vitals are Google’s measurements of real user experience: how fast the main content loads, how much the page shifts while loading, and how quickly the page responds to user interaction. Poor scores affect both your search rankings and your users’ experience. WordPress sites have specific patterns that cause failures in each metric, the same issues appear again and again across thousands of sites. This developer guide covers every significant LCP, CLS, and INP problem unique to WordPress, with specific code fixes you can apply without plugins. For more speed and caching guides, browse our performance hub.

HTML code on screen showing web performance optimization techniques for Core Web Vitals.

Understanding the Three Metrics

Google’s Core Web Vitals consist of three measurements that together describe how a real user experiences a page:

  • Largest Contentful Paint (LCP), How long it takes for the largest visible content element to load. Usually the hero image, H1 heading, or above-fold block. Target: under 2.5 seconds.
  • Cumulative Layout Shift (CLS), How much the page visually shifts during load. Each unexpected movement adds to the CLS score. Target: under 0.1.
  • Interaction to Next Paint (INP), How quickly the page responds to user interactions (click, tap, keyboard input) throughout the entire page lifecycle, not just during initial load. Target: under 200 milliseconds. INP replaced First Input Delay (FID) as a Core Web Vital in March 2024.

All three are measured from real user data via Chrome User Experience Report (CrUX), which Google uses to determine the scores shown in Search Console and PageSpeed Insights. Lab tool scores (from Lighthouse) are useful for debugging but field data is what affects rankings.

Before fixing anything, establish your baseline. Go to Google Search Console > Core Web Vitals and read the real-world data for your top pages. Use PageSpeed Insights for per-URL diagnosis. The WordPress Performance Audit Checklist on this site covers the full baseline measurement process.


Fixing LCP: Largest Contentful Paint

LCP measures the load time of the largest content element visible in the viewport when the page first loads. For most WordPress sites this is the featured image or hero banner. On text-heavy sites it may be the H1 heading or a large paragraph block. The LCP element is identified by the browser at render time, you cannot hardcode it.

The Biggest LCP Killer: Lazy-Loading Your Hero Image

WordPress 5.5 added loading="lazy" to all images automatically. WordPress 6.3 added intelligent LCP detection that avoids lazy-loading the first image, but this detection is not perfect, it applies to images in the main content area but may miss hero images in custom page builder layouts, custom theme templates, or full-width section blocks.

If your LCP element is an image and it has loading="lazy" in the HTML source, that is your primary fix. Remove loading="lazy" from the LCP image and add fetchpriority="high" instead. The browser will immediately begin downloading this image at high priority rather than waiting until it scrolls into view.

Preload the LCP Image in the Document Head

Even with fetchpriority="high", the browser still needs to parse the HTML to discover the image. A <link rel="preload"> in the document head tells the browser to fetch the image before it finishes parsing the page. For a featured image LCP, this can reduce LCP by 200-500ms on average connections.

The snippet above includes the wp_head action that outputs a preload link for single posts and pages. Extend the condition to cover your archive pages and homepage if they have above-fold images.

TTFB as an LCP Input

LCP is measured from the initial navigation start, not from when the browser starts rendering. A slow server response (high TTFB) adds directly to LCP. A page that takes 2 seconds to deliver the first byte cannot achieve a 2.5 second LCP even if all other resources load instantly.

Full-page caching is the most impactful TTFB optimization for WordPress. With a full-page cache serving static HTML, TTFB drops to under 100ms for cached pages. The WordPress TTFB Optimization guide covers the 12 most effective server-side improvements, including full-page caching, Redis object cache, OPcache, and PHP 8.2 migration.

Image Compression and Modern Formats

An LCP image that is 1.5MB in JPEG format will always produce a poor LCP score regardless of server speed, preloading, or CDN. Compress your hero image and convert it to WebP or AVIF. WebP is typically 25-35% smaller than JPEG at equivalent visual quality. AVIF is 30-50% smaller than JPEG but requires more encoding time and has slightly lower browser support (94% as of 2026).

WordPress 5.8+ supports WebP natively. WordPress 6.5+ supports AVIF via GD. For bulk conversion of your existing media library, see WordPress Image Optimization Without Plugins, it covers WP-CLI batch conversion to WebP and AVIF.


Fixing CLS: Cumulative Layout Shift

CLS measures visual instability, how much the page content moves as it loads. Elements that shift because images load without reserved space, ads appear above content, or web fonts swap from fallback to custom are the primary causes.

Images Without Explicit Width and Height

The classic CLS cause in WordPress: images inserted via the block editor without width and height attributes in the HTML. When the browser encounters an img tag without dimensions, it allocates zero space for it. When the image loads, the content below shifts down. WordPress core has added width and height attributes automatically since 5.5, but custom themes and older content may still have unattributed images.

The CSS fix is simple and applies globally:

The CSS file above also covers iframe embeds (YouTube, Vimeo, Google Maps) and font-display configuration. The aspect-ratio approach for iframes is the modern replacement for the padding-bottom percentage hack, it achieves the same space reservation with cleaner, more readable CSS.

Web Fonts and Layout Shift

Web fonts cause CLS through the “Flash of Invisible Text” (FOIT) or “Flash of Unstyled Text” (FOUT). When the custom font loads and replaces the fallback, the text reflows, different font metrics mean different line heights, character spacing, and word wrapping, all of which can shift surrounding content.

font-display: swap reduces FOIT (invisible text) by showing the fallback immediately. But the swap itself causes a layout shift if the fallback and custom font have significantly different metrics. The newer approach is size-adjust, ascent-override, and descent-override CSS descriptors that make fallback fonts match the metrics of your custom font, minimizing the shift when the swap occurs.

Ads and Dynamically Injected Content

Ads inserted above existing content are one of the highest-impact CLS causes. If an ad network injects a 90px banner above your article content after the page loads, every element on the page shifts down by 90px, a CLS score spike. The solution is to reserve space for ads with a fixed-height placeholder div before the ad script loads:

.ad-slot-top {
    min-height: 90px; /* Reserve space matching the ad unit size */
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
}

The same principle applies to cookie consent banners, chat widgets, and notification bars that appear at the top of the page. They must either be loaded above the fold with reserved space, or positioned as overlays that do not push content down.

CLS from Page Builders and Block Patterns

Page builders frequently generate CLS because they render skeleton layouts while loading their scripts, then replace the skeleton with actual content. If your site uses Elementor, Divi, or another page builder, check whether the builder is loading content asynchronously in a way that causes shifts. The fix is usually to enable the builder’s optimized DOM output and disable legacy rendering modes.

Full Site Editing (Gutenberg) block themes generally produce lower CLS than page builders because they render server-side HTML directly without client-side hydration. If CLS from your builder is consistently over 0.1, consider whether the builder is adding enough value to justify the CLS penalty.


Fixing INP: Interaction to Next Paint

INP replaced FID (First Input Delay) as a Core Web Vital in March 2024. While FID measured only the delay before the browser started processing the first input, INP measures the full responsiveness to all interactions throughout the page lifetime, including clicks, taps, and keyboard inputs that happen after the page has loaded.

A poor INP score means users experience sluggish UI: buttons that feel delayed, form fields that lag behind typing, menus that take half a second to open. The root cause is almost always a long task on the main thread that prevents the browser from processing input events promptly.

What Causes Long Tasks in WordPress Sites

The most common sources of long tasks on WordPress sites:

  • Heavy JavaScript from plugins, Page builders, form plugins, chat widgets, and marketing automation tools all load significant JavaScript bundles. If these bundles execute long synchronous tasks during or after page load, they block input handling.
  • Third-party scripts, Analytics scripts, ad tech, and retargeting pixels frequently execute long tasks. Google Tag Manager can serialize dozens of scripts through a single container, creating a long sequence of tasks.
  • React/Vue-based blocks, Heavily JavaScript-driven Gutenberg blocks (particularly from commerce plugins) hydrate complex components after page load, triggering long rendering tasks.
  • Event handler bloat, Attaching expensive computations directly to input events (keyup, mousemove, scroll) without debouncing.

Deferring Non-Critical Plugin Scripts

Many WordPress plugins load their scripts without the defer or async attributes, causing them to block the parser and execute synchronously in document order. Adding defer to non-critical scripts means they download in parallel with HTML parsing and execute after the document is parsed but before DOMContentLoaded. This distributes script execution over time and reduces task clustering.

Use Query Monitor to identify scripts loading without defer. For each one, evaluate whether it is needed on the initial page load or could be deferred. Most plugin scripts, sliders, modals, social sharing buttons, chat widgets, do not need to block parsing.

The script above also shows the PHP pattern for adding defer to specific enqueued script handles via the script_loader_tag filter.


Speculative Prerendering: The Next LCP Frontier

The Speculation Rules API is a browser feature (Chrome 109+) that lets you instruct the browser to prefetch or prerender pages the user is likely to navigate to next. Prerendering goes further than prefetching, it fetches the page, parses HTML, downloads subresources, and executes JavaScript entirely in the background. When the user clicks a link, the page appears instantly because it is already rendered.

The snippet above adds Speculation Rules via wp_head. It prefetches all internal links with “moderate” eagerness (preloads on hover intent) and prerenders with “conservative” eagerness (preloads only on near-certain navigation). The exclusions for /wp-admin/, /cart/, and /checkout/ are important, do not prerender transactional or state-changing pages.

For WooCommerce sites, also exclude product variation pages (/product/* with query strings) and any AJAX-driven pages that modify cart state. Prerendering a page that has side effects (adding an item to cart, updating a form) can cause unexpected behavior.

Browser support: Chrome 109+ (also Edge, Android Chrome). Safari and Firefox do not support Speculation Rules as of 2026, but they safely ignore the JSON script type.

Combining Prefetch and Prerender

Use “prefetch” with moderate eagerness for most internal pages, it downloads the HTML and subresources but does not execute JavaScript, which keeps CPU and memory overhead low. Reserve “prerender” with conservative eagerness only for pages the user is very likely to navigate to next, such as the next article in a series or the “Continue Shopping” link after adding to cart. Prerendering a page executes its JavaScript in a hidden tab, consuming memory and CPU. Apply it selectively to get the navigation-speed benefit without penalizing devices with limited resources.


WordPress-Specific Patterns That Hurt All Three Metrics

Render-Blocking Scripts and Stylesheets

Every render-blocking resource delays the first paint, which delays LCP. Render-blocking scripts prevent HTML parsing; render-blocking stylesheets prevent rendering. Removing render-blocking resources, by adding defer to scripts, inlining critical CSS, and loading full stylesheets asynchronously, is often the single change that produces the largest LCP improvement on sites with multiple blocking resources.

Too Many Plugins Adding JavaScript

Every plugin that adds JavaScript to the front end is a potential INP liability. Deactivate plugins you are not actively using. For plugins you keep, check whether they load scripts on pages where they are not needed. Contact Form 7, for example, loads its scripts on every page by default, not just pages with forms. Conditionally enqueue scripts to pages that actually use them:

add_filter( 'wpcf7_load_js', '__return_false' );
add_filter( 'wpcf7_load_css', '__return_false' );
// Then manually enqueue on pages with forms.

Uncached PHP Computation

PHP computation on every page load contributes to TTFB, which contributes to LCP. Complex WP_Query calls with multiple meta queries, custom taxonomy intersections, or expensive SELECT * patterns without transient caching add 100-500ms per page in some cases. Profile your queries with Query Monitor’s database panel and cache expensive results in transients.

Lazy Loading Below the Fold Images

While loading="lazy" improves page load performance by deferring off-screen images, lazy-loading images that are just below the fold on mobile can increase LCP on those devices. The browser on mobile sees a smaller viewport, an image that appears “above the fold” on desktop may be “the first thing visible” on a narrow screen. Test your LCP element on both desktop and mobile in PageSpeed Insights. They report separately.


How to Track Improvements

After making changes, field data in Search Console takes 28 days to update. Do not wait, use these tools for immediate feedback:

  • PageSpeed Insights, Shows both lab data (immediate) and field data (28-day rolling). The “Diagnose performance issues” section lists specific elements causing LCP, CLS, and INP failures.
  • Chrome DevTools > Performance panel, Record a page load and examine the LCP waterfall in the Timings section. Long tasks appear as red-marked blocks on the main thread. INP can be measured by recording an interaction sequence.
  • web-vitals JavaScript library, Add npm install web-vitals to your theme and log the three metrics to your analytics platform. This gives you per-page, real-user CWV data outside of CrUX’s 28-day aggregation window.
  • CrUX History API, Query historical field data for any origin. Useful for tracking whether your changes are moving the CrUX data that Google uses for ranking.

A practical approach: fix the highest-impact issue (usually LCP), deploy to production, and monitor lab scores with PageSpeed Insights daily for a week. Lab score improvements typically translate to field data improvements within 2-3 weeks once the CrUX data refreshes. For a comprehensive approach to SEO optimization, combine CWV fixes with on-page SEO best practices.


Core Web Vitals Quick Reference

Metric Good Needs Improvement Poor Top Fix for WordPress
LCP < 2.5s 2.5s – 4s > 4s Remove lazy-load from hero; add preload link
CLS < 0.1 0.1 – 0.25 > 0.25 Add width/height to images; reserve space for ads
INP < 200ms 200ms – 500ms > 500ms Defer non-critical scripts; yield in long tasks

Frequently Asked Questions

Do Core Web Vitals directly impact Google rankings?

Yes, since the Page Experience update in 2021. Google uses CWV as a ranking signal, with “Good” scores giving a small positive signal over “Needs Improvement” or “Poor” scores. The impact is meaningful at the margin, for two pages with similar content quality and authority, the one with better Core Web Vitals will generally rank higher. For most sites, content quality and backlinks remain more dominant signals, but CWV becomes a tiebreaker and is increasingly weighted in competitive queries.

Why is my PageSpeed Insights score different from my Search Console score?

PageSpeed Insights lab score is from a single simulated Lighthouse run under controlled conditions. Google Search Console CWV score is based on 28 days of real Chrome user data from CrUX. Real users on slower devices, slower connections, and from different geographic locations will produce different scores than a lab test. The Search Console score is what affects rankings. Focus on improving field data, not lab scores.

My LCP is fast on desktop but slow on mobile. Why?

Several factors: mobile devices have slower CPUs (heavier JavaScript execution), mobile connections may be slower (image delivery), and the mobile viewport shows different above-fold content than desktop. A responsive image with a large desktop src but no srcset may deliver a 1200px image to a 390px device. Add proper srcset and sizes attributes so mobile devices get appropriately sized images. WordPress generates srcset automatically for images processed through the media library, but custom background images set via CSS need separate handling.

How does the Heartbeat API affect INP?

The WordPress Heartbeat API fires AJAX requests every 15 seconds in the editor and every 60 seconds on the front end (when logged in). Each AJAX response triggers PHP callbacks and database queries. On the front end for logged-in users, the Heartbeat can create periodic input responsiveness dips. The Heartbeat API guide on this site shows how to reduce its frequency or disable it on non-editor pages.

Is there a WordPress plugin that fixes Core Web Vitals automatically?

No single plugin fixes all three metrics, because INP, LCP, and CLS have different root causes. Performance plugins like WP Rocket, NitroPack, or Perfmatters address specific LCP and CLS causes (image lazy loading, critical CSS, render-blocking resources). But INP caused by heavy plugin JavaScript, and CLS from theme-specific layout patterns, require code-level fixes. Use these plugins as a starting point, then measure what remains with PageSpeed Insights and fix the remaining issues manually.


Final Thoughts

Core Web Vitals are not abstract scores, they measure real user experience. An LCP over 4 seconds means your hero image takes longer to load than most users are willing to wait. A CLS over 0.25 means content visibly jumps while users try to read or click. An INP over 500ms means buttons feel broken.

WordPress-specific fixes are concrete and repeatable. Remove lazy-loading from the LCP image. Add fetchpriority=high and a preload link. Explicit image dimensions eliminate CLS for free. Deferring non-critical plugin scripts reduces INP without removing features. Speculative prerendering makes navigation feel instant for users on Chrome.

None of these require page speed plugins, CDN migrations, or infrastructure upgrades. They are code-level changes that take an afternoon to implement and produce measurable, lasting improvements. Start with the metric where your Search Console data shows the most “Poor” URLs, apply the relevant fixes, and monitor the field data over the following month.

Visited 5 times, 1 visit(s) today

Last modified: March 26, 2026