Web Development

Core Web Vitals: What They Are and How to Fix Them

Jul 12, 2026 • 11 min read
#Web Development #SEO #Performance
Core Web Vitals: What They Are and How to Fix Them

Your site loads fine on your laptop over office fibre, but Google Search Console keeps flagging URLs as "Needs improvement" and your organic traffic has flattened. That gap is what Core Web Vitals measure: not how fast your site feels to you, but how it behaves for real users on mid-range Android phones over patchy 4G, which is where most Indian traffic actually comes from.

This guide covers what the three current metrics measure, how to read your own data honestly, and the specific fixes that move the numbers — in rough order of how much work they cost versus how much they help.

What Core Web Vitals actually measure

Core Web Vitals are three field metrics Google collects from real Chrome users who have opted into usage statistics. That last part matters more than most people realise. These are not synthetic lab scores. They come from actual visits on actual devices, aggregated over a rolling 28-day window, and reported at the 75th percentile. So when Google says your LCP is 3.4 seconds, it means one in four of your visitors waited longer than that.

LCP — Largest Contentful Paint

LCP marks the moment the largest visible element in the viewport finishes rendering. On most pages that is a hero image, a background image, a heading block, or a video poster frame. Good is under 2.5 seconds. Poor is above 4 seconds. Anything in between is the "needs improvement" band.

LCP is essentially a question about your critical path: how quickly can the browser go from "user tapped the link" to "the main thing on this page is on screen"? Every DNS lookup, redirect, render-blocking stylesheet, and oversized JPEG sits in that path.

INP — Interaction to Next Paint

INP replaced First Input Delay as a Core Web Vital in March 2024. If you are reading an older tutorial that talks about FID, that advice is out of date and, worse, it is optimising for the wrong thing. FID only measured the delay before the browser started handling your first tap. INP measures the full round trip — tap, event handler runs, next frame painted — across all interactions on the page, and reports roughly the worst one.

Good is under 200ms. Poor is above 500ms. INP is the metric that catches the site which loads fast and then feels like treacle: the mega-menu that takes half a second to open, the quantity stepper on a product page that lags behind your thumb, the filter checkbox that freezes the list for 700ms while JavaScript re-sorts 400 products.

CLS — Cumulative Layout Shift

CLS is a unitless score measuring how much visible content jumps around without the user causing it. Good is under 0.1. Poor is above 0.25.

Everyone has experienced bad CLS. You go to tap "Add to cart", a banner ad or a late-loading font pushes the page down, and you tap something else entirely. On a phone that is genuinely infuriating, and it is the single most common reason people bounce off a page they were otherwise interested in.

MetricGoodNeeds improvementPoorWhat it catches
LCP≤ 2.5s2.5s – 4.0s> 4.0sSlow loading of main content
INP≤ 200ms200ms – 500ms> 500msSluggish response to taps and clicks
CLS≤ 0.10.1 – 0.25> 0.25Content jumping during load

How much does this actually affect your rankings?

Here is the honest answer that most agencies will not give you: Core Web Vitals are a real ranking signal, but a small one. They are a tiebreaker, not a lever. If your page is the fourth-best answer to a query, fixing your LCP will not make it the best answer. Content relevance, search intent match, and links still dominate.

So why bother? Two reasons that have nothing to do with the ranking signal itself.

First, conversion. The mechanism is straightforward: every second a user waits is a second in which they can change their mind, get distracted, or hit the back button. Every layout shift is a chance to mis-tap. Slow, janky pages leak revenue on a checkout flow in a way that has nothing to do with Google.

Second, Core Web Vitals are a proxy for engineering discipline. Sites with terrible vitals usually have terrible vitals for reasons — four analytics scripts, an uncompressed 3MB hero, a page builder plugin rendering 200KB of inline CSS — and those same reasons cause bugs, security exposure, and maintenance pain.

If your site is already in the green, stop. Do not spend three weeks shaving LCP from 2.1s to 1.7s. There is no bonus for being extra green, and that time is better spent on content or on the checkout funnel.

Getting data you can trust

Field data versus lab data

This trips up more teams than any other part of the process. There are two kinds of measurement and they disagree constantly.

  • Field data (CrUX) is what Google actually uses. Sources: Search Console's Core Web Vitals report, the CrUX section at the top of PageSpeed Insights, and the CrUX API or BigQuery dataset. It is real, it is what counts, and it lags by 28 days.
  • Lab data is a simulated run on Google's hardware with a throttled connection. Sources: the Lighthouse section of PageSpeed Insights, Chrome DevTools Lighthouse panel, WebPageTest. It is instant and reproducible, which makes it good for debugging, but it does not measure INP at all because there is no real user to interact with the page.

Use field data to decide whether you have a problem. Use lab data to find out what is causing it. Never report a Lighthouse performance score to a client as if it were a Core Web Vitals result — the 0–100 score is a weighted composite that includes metrics Google does not rank on.

Reading Search Console properly

Search Console groups URLs into buckets by similarity, so you will typically see a handful of groups covering thousands of URLs. Fix the template, fix the whole group. The report is also split by device, and mobile is almost always worse. If mobile is red and desktop is green, that is normal and mobile is the one to fix, since it is where most of your traffic sits.

Measuring real INP yourself

If you need INP data faster than the 28-day CrUX window, add the web-vitals JavaScript library to your site and send the values to your analytics. It reports the actual metric with the element that caused the worst interaction attached, which is far more useful than guessing. A few lines of code, and it turns "the site feels slow" into "the category filter handler is blocking for 640ms".

Fixing LCP

Find the LCP element first

Do not optimise blind. Open Chrome DevTools, go to the Performance panel, record a page load with mobile throttling, and look for the LCP marker on the timeline. Chrome tells you exactly which element it is. Nine times out of ten it is one image.

Serve the right image, at the right size, in the right format

The most common failure we see: a 2400px-wide hero JPEG at 900KB being displayed at 380px on a phone. The browser downloads all 900KB, decodes it, and throws away most of the pixels.

  • Serve WebP or AVIF with a JPEG fallback. WebP typically cuts file size by a quarter to a third at visually identical quality, AVIF more.
  • Use srcset and sizes so phones get phone-sized files. A 400px-wide hero should be roughly 30–60KB, not 900KB.
  • Set explicit width and height attributes on every image. This also fixes CLS, so you get two metrics for one change.
  • Add loading="lazy" to images below the fold — and never to the LCP image, which is a surprisingly common own goal that adds hundreds of milliseconds.
  • Add fetchpriority="high" to the LCP image so the browser stops treating it as equal to the footer logo.

Kill render-blocking resources

Every stylesheet in the <head> blocks the first paint. Every synchronous script does too. Practical steps:

  • Inline the critical CSS needed for above-the-fold content, load the rest asynchronously.
  • Add defer to every script that does not need to run before paint. In practice that is nearly all of them.
  • Self-host fonts, subset them to the characters you use, and set font-display: swap. Third-party font CDNs add a DNS lookup, a TLS handshake, and a second round trip before a single glyph renders.
  • Cut the analytics and marketing tags. A tag manager container with fourteen tags in it is a performance problem wearing a suit. Audit which ones anyone actually looks at.

Fix the server side

If your Time to First Byte is already 900ms, no amount of image optimisation will get LCP under 2.5s. Look at hosting location — a server in Virginia serving customers in Chandigarh adds roughly 200–300ms of pure latency per round trip. Use an Indian or Singapore region, or put a CDN in front. Then add full-page caching for anonymous visitors and check for slow database queries on your heaviest templates.

Fixing INP

INP problems are almost always JavaScript problems, and specifically main-thread problems. The browser can only do one thing at a time on the main thread, so when your event handler runs for 400ms, nothing repaints.

Break up long tasks

Any task over 50ms is a long task. If a click handler filters, sorts, and re-renders a large list synchronously, split the work: do the visible part immediately, yield back to the browser, then continue. Yielding with scheduler.yield() where available (or a setTimeout of zero as a fallback) lets the browser paint a response between chunks, which is exactly what INP measures.

Show feedback before doing the work

A large part of INP is perceptual. If a tap sets a "loading" state and paints it in 30ms, then does the heavy work afterwards, INP records 30ms. Same total work, far better metric, and a far better experience — the user knows their tap registered.

Reduce what runs at all

  • Trim your JavaScript bundle. Code-split by route so the product page does not ship the checkout logic.
  • Audit third-party scripts. Chat widgets, heatmap recorders, and A/B testing tools are frequent INP offenders because they attach listeners to everything.
  • Avoid layout thrashing — reading a layout property such as offsetHeight immediately after writing a style forces a synchronous reflow. In a loop, that is death.
  • Debounce input handlers, but keep the debounce short. 100–150ms is usually right for search-as-you-type.

Fixing CLS

CLS is the cheapest of the three to fix and gives the most immediate visible improvement. Most CLS comes from four sources.

Images and embeds without dimensions

Set width and height on every image, iframe, and video. The browser reserves the space before the file arrives. If your layout is responsive, use CSS aspect-ratio so the reserved box scales correctly.

Ads, banners, and injected content

Anything injected after load — an ad slot, a cookie notice, a promotional strip, a "you have items in your cart" bar — must have space reserved for it, or be positioned so it does not push content. Fixed-position or bottom-anchored notices avoid the problem entirely.

Web fonts

When a fallback font is swapped for a webfont with different metrics, every line of text reflows. Use size-adjust and the ascent-override family of descriptors on your @font-face rule to match the fallback's metrics to the real font, or pick a fallback stack that is already close.

Client-side rendered content

Single-page apps that render a skeleton and then swap in content often shift badly. Make the skeleton the same size as the content it replaces. If it is a list, render placeholder rows at the real row height.

A realistic order of work

If you are starting from a genuinely poor set of scores on a typical WordPress or custom PHP site, this is the sequence that gives the most improvement per hour spent:

  1. Image audit. Compress, convert to WebP, add dimensions, add srcset, fix lazy-loading on the hero. Usually one to two days, and often moves LCP by a second or more on its own.
  2. Caching and hosting. Full-page cache, correct server region, CDN for static assets. Half a day if the infrastructure allows it.
  3. Third-party script cull. Remove what nobody reads, defer the rest. Half a day, often the biggest single INP win.
  4. Render-blocking CSS and fonts. Critical CSS, self-hosted subset fonts. One to two days.
  5. JavaScript work. Bundle splitting, breaking up long tasks. This is the expensive one — a week or more — so only do it if steps 1–4 left you short.

Budget-wise, a focused Core Web Vitals remediation on a mid-sized business site typically runs ₹25,000 to ₹80,000 depending on how much of step 5 is needed. If a proposal quotes ₹5,000 for "full speed optimisation", it is a plugin install, and a caching plugin alone will not fix an INP problem.

When a rebuild beats optimisation

Sometimes the honest answer is that the existing site cannot get to green without disproportionate effort. Warning signs: a page builder generating thousands of nested divs, a theme with fifteen bundled plugins you cannot remove, or 2MB of jQuery-era JavaScript that everything depends on. In those cases you can spend ₹60,000 fighting the platform to reach "needs improvement", or spend more once and be done.

Conversely, if your site is a reasonably clean custom build sitting at LCP 3.1s, do not let anyone sell you a rebuild. That is an afternoon of image work and a caching layer.

Conclusion

Pull your field data from Search Console first and confirm you actually have a problem — a good number of sites flagged by a random online scanner are perfectly fine in CrUX. If you do have a problem, work the list in order: images, caching, third-party scripts, then CSS and fonts, and only then JavaScript refactoring.

Aim for green, then stop and put your effort back into content and conversion. Core Web Vitals are worth fixing because slow, jumpy pages lose customers, not because a passing grade wins you a ranking boost. Treat them as a hygiene standard rather than a growth strategy and you will spend your budget in the right place.

Back to Blog