To fix Core Web Vitals, find which metric fails on which group of pages in Search Console, then fix that metric at its cause: LCP by shortening the path to the main image or headline, INP by breaking up long JavaScript tasks, and CLS by reserving space for everything that loads late. Fix the shared template, not one URL, because Google groups similar pages and assesses them together. Search Console shows the result about 28 days after the fix goes live.
Whether speed is worth the effort for your rankings is covered in how a slow website affects SEO. This guide assumes you have already decided to fix it.
How to find which metric and which pages fail
Open Search Console's Core Web Vitals report first, because it tells you which metric fails on which page type. Google's Core Web Vitals report documentation (Google Search Console Help) states that "URLs in the report are grouped into pages that have a similar user experience" and that the data "comes from the CrUX report", the Chrome User Experience Report built from real Chrome visits.
Work through these 4 steps in order:
- Pick the device. Mobile and desktop are assessed separately, so check both tabs.
- Open each Poor or Needs improvement issue. The issue name tells you the metric, for example "INP issue: longer than 200ms (mobile)".
- Map example URLs to templates. Ten failing URLs that are all product pages are one problem, not ten.
- Test one example URL per template in PageSpeed Insights. Read the field data at the top for the verdict and the diagnostics underneath for the cause.
Lab data versus field data
Field data decides whether you pass, and lab data shows you why. Google's PageSpeed Insights documentation (Google for Developers) states that field data covers "the previous 28-day collection period" at the 75th percentile, while lab data comes from one simulated load in a controlled environment, so "the values may differ."
The practical consequence is that a green Lighthouse score does not mean you pass. INP in particular barely shows in lab tests, because Lighthouse does not click or type. Reproduce INP problems by recording real interactions in Chrome DevTools > Performance.
How to fix LCP (Largest Contentful Paint)
Fix LCP by measuring which of its 4 sub-parts is slow, then working on that one. Google's guide to optimising LCP (web.dev, updated 2025) breaks every LCP into these 4 parts, with a target share of the total for each:
- Time to first byte (TTFB): server response time, about 40% of LCP.
- Resource load delay: the gap between TTFB and the browser starting to download the LCP image, under 10%.
- Resource load duration: the image download itself, about 40%.
- Element render delay: the gap between download finishing and the element appearing, under 10%.
PageSpeed Insights shows this breakdown under the "Largest Contentful Paint element" diagnostic. The two "delay" parts are pure waste: neither one involves downloading anything useful.
Cut resource load delay
Make the LCP image discoverable in the HTML and give it high priority. A hero image set as a CSS background, or injected by a slider script, is invisible to the browser until that CSS or JavaScript runs.
<img src="/hero.webp" width="1200" height="630"
fetchpriority="high" alt="Product photo">
The same web.dev guide says "Never lazy-load your LCP image", and warns that marking more than one or two images as high priority makes the hint useless. Google's Fetch Priority guide (web.dev) lists support in Chrome 102, Firefox 132 and Safari 17.2, and reports a Google Flights test where LCP improved from 2.6 seconds to 1.9 seconds.
Cut load duration and TTFB
Shrink the LCP file and the server wait. Serve the hero as WebP or AVIF at the size it displays, put static files on a CDN, and enable full-page caching so the server does not rebuild the HTML for every visitor.
Cut render delay
Remove render-blocking CSS and JavaScript from the head. Defer non-critical scripts, inline the small amount of CSS the first screen needs, and drop A/B testing tools that hide the page until they load.
How to fix INP (Interaction to Next Paint)
Fix INP by finding the slow interaction and shortening whichever of its 3 phases is longest. Google's guide to optimising INP (web.dev, updated 2025) splits every interaction into input delay, processing duration and presentation delay.
These are the usual causes for each phase:
- Input delay: other scripts are busy when the user taps, for example a chat widget or analytics tag starting up.
- Processing duration: your own event handlers do too much work, for example filtering a 500-item product list on every keystroke.
- Presentation delay: the browser needs a long time to redraw, for example after replacing a large chunk of the DOM.
Break up long tasks
Split long tasks so the browser can respond between chunks. Google's guide to long tasks (web.dev) defines a long task as "any task that takes longer than 50 milliseconds" and recommends scheduler.yield(), with setTimeout as the fallback.
function yieldToMain() {
if (globalThis.scheduler?.yield) return scheduler.yield();
return new Promise((resolve) => setTimeout(resolve, 0));
}
async function handleFilter(items) {
for (const chunk of chunks(items, 50)) {
renderChunk(chunk);
await yieldToMain(); // let the browser paint and handle input
}
}
Keep the fallback. The same guide lists scheduler.yield() support from Chrome 129 and Firefox 142 with no Safari support, and MDN's Scheduler.yield() reference (Mozilla) marks it as not Baseline.
Do less work on each interaction
Update the visible part of the screen first and defer the rest. Debounce search inputs, show the menu before sending the analytics event, and stop running heavy handlers on every scroll event.
How to fix CLS (Cumulative Layout Shift)
Fix CLS by reserving space for every element before it loads. Google's guide to optimising CLS (web.dev, updated 2025) names the main causes: images without dimensions, ads and embeds, dynamically injected content and web fonts.
Images and video without dimensions
Add width and height to every image and video, as in the LCP example above. The browser uses them to calculate the aspect ratio and holds the space before the file arrives. For responsive containers, CSS aspect-ratio: 16 / 9 does the same job.
Ads, embeds and injected banners
Give each ad slot, YouTube embed and cookie banner a fixed min-height in CSS. web.dev advises against collapsing the space when no ad is returned, and recommends a placeholder instead. Cookie banners belong at the bottom of the viewport as an overlay, not pushed in above the content.
Web fonts
Stop the text from reflowing when the web font replaces the fallback. web.dev notes that font-display: optional avoids the re-layout, and that size-adjust and the override descriptors match the fallback's size to the web font.
@font-face {
font-family: "Brand";
src: url("/fonts/brand.woff2") format("woff2");
font-display: optional;
}
Platform notes: WordPress and Next.js
The fixes above apply to every site, but each platform has its own common failure points.
WordPress
WordPress handles part of LCP for you. The WordPress 6.3 image performance update (Make WordPress Core, 2023) added automatic fetchpriority="high" to the image most likely to be the LCP. Three things still break it:
- Sliders and page builders that load the hero image through JavaScript or as a CSS background.
- Lazy-load plugins that apply
loading="lazy"to every image, including the hero. - Plugin bloat that adds scripts to every page, which drives up INP input delay.
Check the INP culprits in DevTools > Performance and look at the script URLs: /wp-content/plugins/<name>/ tells you exactly which plugin owns the long task.
Next.js
Next.js handles fonts well by default but leaves image priority to you. In Next.js 16 the priority prop on next/image is deprecated in favour of preload, per the Next.js Image component reference (Vercel), so set preload on the hero image only. next/font self-hosts fonts and generates an adjusted fallback to reduce layout shift, as the Next.js Font reference (Vercel) describes.
For INP, the common cause is hydration: large client components that must run before the page responds. Keep components as Server Components unless they need interactivity, and load third-party scripts through next/script with strategy="lazyOnload" when they are not needed for the first interaction.
Where SEO, code and security overlap in Core Web Vitals
A failing INP score is often a tracking problem, and sometimes a security problem. As Head of Automation at a US marketing agency, I work inside Google Tag Manager setups, and containers grow by one tag per campaign unless someone deliberately removes the old ones. Each tag adds main-thread work at the exact moment visitors start tapping. Auditing the container and removing tags for finished campaigns fixes INP without touching the site's code.
The security side matters too. Scripts you did not add, for example an unfamiliar domain in the DevTools Network panel, are a sign of injected malware, and no performance fix removes them. My guide on removing malware from a WordPress site covers that cleanup.
For problems in server configuration, rendering architecture or a custom theme, a technical SEO consultant who also writes code saves weeks of back and forth between an SEO and a developer.
How long until Search Console shows the fix
Search Console reflects a fix about 28 days after it goes live, because CrUX data covers a rolling 28-day window. Old slow visits keep counting until they age out, so the report improves gradually rather than overnight.
Start validation for each fixed issue in the Core Web Vitals report. Google's documentation describes this as a "28-day monitoring session", and if the issue appears again during that window, validation fails and you need to fix the remaining URLs and restart it. Check PageSpeed Insights field data for individual URLs in the meantime, and confirm the change in lab data the same day you deploy.
Frequently asked questions
Why do I pass Lighthouse but fail Core Web Vitals?
Lighthouse runs one simulated load on a single device, while Core Web Vitals use 28 days of real Chrome visits at the 75th percentile. Real visitors on slower phones and networks, and real clicks that Lighthouse never makes, are what fail the assessment.
Which Core Web Vital should I fix first?
Fix the metric marked Poor on the page template with the most traffic first, usually on mobile. A Poor rating on a template that holds most of your landing pages affects more visitors than a Needs improvement rating anywhere else.
What does "Core Web Vitals assessment: failed" mean?
It means at least one of LCP, INP or CLS is above its "good" threshold at the 75th percentile of real visits. A page passes only when all three metrics with enough data are good.
Does a caching plugin fix Core Web Vitals on WordPress?
A caching plugin fixes TTFB and part of LCP, but it does not fix INP or most CLS problems. Those come from JavaScript work, missing image dimensions, ads and fonts, which need changes to the theme, plugins or scripts.
How long does it take for Core Web Vitals fixes to show in Google?
Search Console takes about 28 days to reflect a fix, because its data comes from a rolling 28-day window of real Chrome visits. Validation in the Core Web Vitals report also runs as a 28-day monitoring session.
