Understanding Core Web Vitals

Keyboard shortcuts
  • JNext lesson
  • KPrevious lesson
  • /Search lessons
  • EscClear search

I spent the first five years of web performance work obsessing over the wrong numbers. Total page load time. Fully loaded time. Number of requests. These metrics told me something, but they didn’t tell me what actually mattered to the person sitting on the other side of the screen. Google’s Core Web Vitals changed that. They measure what users feel, not what servers report. And once I started thinking about performance from the user’s perspective, everything clicked.

Core Web Vitals are three specific metrics that Google uses to evaluate page experience. They’re not the only ranking factors, and they’re not the most important ones. But they’re the only performance metrics baked directly into Google’s algorithm. If you’re running a WordPress blog and you want organic traffic, these numbers matter.

What Core Web Vitals Are and Why Google Chose These Metrics

Google tested dozens of potential metrics before settling on three. They wanted metrics that matched how real users perceive a web page. Not technical abstractions, but actual human experience.

When you load a web page, three things determine whether it feels fast or slow. First, how quickly does meaningful content appear? You’re staring at a blank or half-rendered screen. That’s frustrating. Second, when you tap or click something, does it respond immediately? A button that takes 400ms to react feels broken. Third, does stuff jump around while the page loads? You’re about to tap a link and suddenly an ad pushes it down and you hit something else. That’s infuriating.

Google built a metric for each of these experiences. LCP (Largest Contentful Paint) measures visual loading. INP (Interaction to Next Paint) measures responsiveness. CLS (Cumulative Layout Shift) measures visual stability. Together, they capture the three biggest complaints users have about slow websites.

What I appreciate about this framework is that it forces developers and site owners to think about real experience. Before Core Web Vitals, you could have a “fast” site by technical metrics that still felt janky and broken to visitors. Now there’s a shared vocabulary between what Google measures and what users feel.

LCP: Largest Contentful Paint

LCP measures how long it takes for the biggest visible element on the page to render. For most blog posts, this is either the hero image or the main heading text block. For homepages, it might be a large banner image or a featured post thumbnail.

What “good” looks like. Google says under 2.5 seconds is good. Between 2.5 and 4.0 seconds needs improvement. Over 4.0 seconds is poor. I aim for under 2.0 seconds because the threshold could tighten, and because 2.5 seconds still feels sluggish to me.

Why WordPress sites struggle with LCP. The most common causes I see on WordPress blogs, and I’ve audited hundreds at this point:

Slow server response. If your TTFB is 800ms, you’ve already burned a third of your LCP budget before the browser even starts rendering. Cheap shared hosting is the number one cause of bad LCP scores. No front-end trick can fix a slow server.

Unoptimized hero images. A 2MB JPEG hero image on a blog post will destroy your LCP. The browser has to download the entire image before it can paint it. Serving a properly sized WebP or AVIF at 80% quality can cut that download from 2MB to 200KB. We’ll cover image optimization in Chapter 5.

Render-blocking CSS and JavaScript. Your browser can’t paint anything until it’s downloaded and parsed all the CSS in the <head>. If you have 300KB of CSS (common with page builders), the browser sits there waiting. Same with render-blocking JavaScript. Every stylesheet and script in the head is a roadblock.

Web fonts. Custom fonts need to be downloaded before text renders (depending on your font-display strategy). If your fonts are large or served from a slow CDN, text won’t appear until they arrive. I’ve seen font loading alone add 500ms-1.5 seconds to LCP.

How to fix LCP problems. Start with hosting (Chapter 3). Then optimize your LCP element directly. If it’s an image, compress it, serve it in WebP/AVIF, and use fetchpriority="high" and preload hints. If it’s text, make sure your fonts load fast or use font-display: swap. Remove render-blocking resources by deferring non-critical CSS and JavaScript.

INP: Interaction to Next Paint

INP replaced FID (First Input Delay) as the official responsiveness metric in March 2024. FID only measured the first interaction. INP measures all interactions throughout the entire page visit and reports the worst one (technically, the 98th percentile).

Think of it this way. FID was like grading a restaurant on the first bite of the appetizer. INP grades on every dish served during the entire meal. You can’t hide a slow interaction behind a fast first click anymore.

What INP measures. When a user clicks a button, taps a link, or presses a key, INP measures the time from that action to the next visual update on screen. It captures the full cycle: input delay (waiting for the main thread to be free), processing time (running the event handler), and presentation delay (updating the screen with the result).

Target. Under 200ms is good. Between 200ms and 500ms needs improvement. Over 500ms is poor.

Why WordPress sites struggle with INP. This is where WordPress has a real problem, and it’s mostly caused by JavaScript.

Heavy page builders. Elementor, Divi, and similar builders load hundreds of kilobytes of JavaScript on every page. This JavaScript occupies the browser’s main thread. When a user clicks something while that JavaScript is executing, the browser can’t respond until the JavaScript finishes. The result: a click that takes 300-500ms to register.

Too many plugins with front-end JavaScript. Every slider, popup, analytics script, chat widget, and social sharing plugin adds JavaScript. Each one competes for the main thread. Stack 10-15 of these together and you’ve got a main thread that’s constantly busy. I’ve measured sites where the main thread was blocked for 3-4 seconds during page load, and any interaction during that window felt completely unresponsive.

Third-party scripts. Google Analytics, Facebook Pixel, ad networks, cookie consent tools. Each one adds JavaScript that runs on the main thread. Ad-heavy sites are particularly bad because ad networks load and execute JavaScript for every ad slot.

How to fix INP problems. Reduce JavaScript. That’s the short answer. The longer answer involves auditing every script on your page, removing what isn’t needed, deferring what isn’t critical, and using a caching plugin that handles JavaScript optimization well. FlyingPress is what I use because it delays JavaScript execution until user interaction, which directly improves INP.

CLS: Cumulative Layout Shift

CLS is the metric that measures how much the page layout shifts unexpectedly during loading. Every time a visible element moves without the user causing it, that’s a layout shift. CLS sums up all the unexpected shifts and gives you a score.

Target. Under 0.1 is good. Between 0.1 and 0.25 needs improvement. Over 0.25 is poor.

The most common causes on WordPress sites. I see the same CLS problems on almost every WordPress blog I audit:

Images without dimensions. If you don’t specify width and height attributes on your images (or use CSS aspect-ratio), the browser doesn’t know how much space to reserve. It renders the page, then the image downloads, and everything below it shifts down. This is the single biggest CLS cause on WordPress sites. The good news: WordPress has added width and height attributes to images automatically since version 5.5. But many themes and plugins strip them out.

Ads that load late. Display ads (AdSense, Mediavine, Raptive) are notorious CLS sources. The ad container loads empty, then the ad fills in and pushes content down. The fix is reserving space for ads with min-height CSS on the ad container. If you’re running Mediavine, they have a CLS optimization setting. Turn it on.

Web fonts causing text reflow. When the browser first renders with a fallback font, then swaps in the custom font, text can resize and shift. Using font-display: swap with properly matched fallback fonts reduces this. Using font-display: optional eliminates it entirely but means some visitors might see the fallback font.

Dynamically injected content. Newsletter popups, cookie consent banners, and sticky headers that push content down instead of overlaying it. These all create layout shifts. A cookie banner should overlay the bottom of the screen, not push your content down by 60 pixels.

Embeds without reserved space. Twitter embeds, YouTube embeds, and Instagram embeds all load asynchronously. The embed starts as a small loading placeholder, then expands to full size. If you don’t reserve space with aspect-ratio boxes, everything shifts.

CLS is the easiest Core Web Vital to fix because the causes are straightforward and the solutions are mostly CSS. I typically fix CLS issues in 30-60 minutes on most WordPress sites.

How to Measure: The Tools That Matter

You need two types of measurement: lab data (synthetic tests you run on demand) and field data (real user measurements collected over time). Both matter, but they tell you different things.

PageSpeed Insights (pagespeed.web.dev). This is your primary tool. It shows both lab data (a Lighthouse test run on Google’s servers) and field data (real user metrics from the Chrome User Experience Report). The field data section at the top is what Google actually uses for ranking. The lab data below is useful for diagnosing problems, but don’t obsess over the score.

Chrome DevTools. Open DevTools (F12), go to the Performance tab, and record a page load. This gives you a detailed timeline of every resource loaded, every script executed, and every layout shift. It’s technical, but it’s the most powerful diagnostic tool available. The “Lighthouse” tab in DevTools also runs PageSpeed audits locally.

WebPageTest (webpagetest.org). The gold standard for detailed performance testing. It lets you test from specific locations, on specific devices, with specific connection speeds. The filmstrip view shows you exactly what the user sees at each point during loading. The waterfall chart shows every resource and how long each took.

Google Search Console. The Core Web Vitals report in Search Console shows how your actual pages perform for real users over time. This is your source of truth for whether Google considers your pages fast or slow. Check it monthly at minimum.

Chrome Web Vitals Extension. A browser extension that shows LCP, INP, and CLS in real-time as you browse your site. Good for quick checks, but remember you’re testing on your device and connection, which might not represent your audience.

Field Data vs. Lab Data

This distinction trips people up, and it’s important.

Lab data is what you get from running a Lighthouse test or WebPageTest. It’s a synthetic test run once, from one location, with controlled conditions. It’s useful for diagnosing problems and testing fixes. But it’s not what Google uses for ranking.

Field data is collected from real Chrome users visiting your site over a 28-day rolling window. It’s what Google uses for Core Web Vitals assessment. It reflects actual user experience across different devices, connections, and locations.

Here’s why this matters: your lab score can be 95 while your field data shows failing metrics. How? Because your lab test ran on a fast server in a data center. Your real visitors are on slow phones in rural areas. Or your lab test tested a clean version of the page without ads, while real visitors get the ad-heavy version.

The reverse can happen too. Your lab score might be 60, but your field data passes all Core Web Vitals. This happens when your audience is mostly on fast connections with modern devices.

I’ve had clients panic over a 50 on their PageSpeed score when their field data was all green. And I’ve had clients proudly show me their 90+ score while their field data was all red. The score is a guide. The field data is reality.

When Google doesn’t have enough field data for your specific page (you need about 1,000 pageviews per month to qualify), it uses data from your entire origin (domain) or doesn’t show field data at all. For newer or lower-traffic sites, lab data is all you have. That’s fine. Just know it’s approximate.

Setting Your Baseline

Before you change anything, measure everything. You need a baseline to know whether your optimizations actually worked.

Step 1: Run PageSpeed Insights on 5 key pages. Your homepage, your most-trafficked blog post, a category/archive page, a page with lots of images, and any page with ads. Record the mobile and desktop scores, plus the individual LCP, INP, and CLS values for each.

Step 2: Check Search Console. Go to Experience > Core Web Vitals. Record how many URLs are in each category (Good, Needs Improvement, Poor) for both mobile and desktop. Screenshot this. You’ll compare it in 30 days.

Step 3: Test with WebPageTest. Run a test on your homepage from the closest server to your primary audience. Use “Mobile – 4G” as the connection speed. Record the fully loaded time, TTFB, LCP, and total page weight.

Step 4: Document your setup. Write down your hosting provider and plan, your theme, your active plugins (with count), and your current PHP version. You’ll need this as you make changes.

Keep all these numbers in a spreadsheet or document. After each chapter’s optimizations, re-test and compare. Seeing the numbers improve is motivating, and it proves that what you’re doing is working.

The Metrics That Don’t Matter

I need to address this because I see bloggers waste enormous time chasing the wrong numbers.

The PageSpeed score itself. The score from 0-100 is a weighted combination of several metrics. It’s a rough guide, not a grade. A site scoring 68 with passing Core Web Vitals is outperforming a site scoring 85 with failing Core Web Vitals in Google’s eyes. Don’t chase 100. Chase green Core Web Vitals.

I’ve seen sites with a score of 55 that load beautifully and feel fast. The score was low because of third-party scripts (ad networks) that the site owner can’t control. But the actual user experience was excellent, and the field data proved it.

Number of requests. This was a big deal when HTTP/1.1 was standard because browsers could only make 6 connections per domain simultaneously. With HTTP/2 and HTTP/3, multiplexing means hundreds of requests can happen in parallel. A page with 80 requests on HTTP/2 can load faster than a page with 20 requests on HTTP/1.1. The total weight of those requests matters more than the count.

Fully loaded time. This is the time until absolutely everything finishes loading, including deferred scripts, lazy-loaded images below the fold, and analytics beacons. It can be 10-15 seconds on a perfectly fast page because non-visible resources are loading in the background. What matters is how fast the visible, interactive part of the page loads. That’s what LCP and INP measure.

GTmetrix grades. GTmetrix is a fine tool, but their letter grades are based on their own scoring system, not Google’s. An “A” on GTmetrix means nothing to Google. A “C” on GTmetrix with passing Core Web Vitals in the field is better for your rankings.

Pingdom scores. Same issue. Pingdom uses its own scoring methodology. It’s another data point, but it’s not what Google uses. I stopped recommending Pingdom years ago because it caused more confusion than clarity.

Focus on three things: passing Core Web Vitals in the field (as shown in PageSpeed Insights and Search Console), acceptable TTFB (under 200ms), and fast perceived loading (LCP under 2.5 seconds). Everything else is noise.

Don’t let perfect scores become the enemy of a fast site. I’ve watched bloggers spend weeks trying to squeeze from 92 to 97 on PageSpeed while their actual user experience was already excellent. That time would’ve been better spent writing content.

The goal of this course isn’t to get you a perfect score. The goal is to get your site loading fast enough that speed is never the reason you lose a visitor, a subscriber, or a sale. And that’s a much more practical target.


Chapter Checklist

  • [ ] Can explain what LCP, INP, and CLS measure in plain English
  • [ ] Ran PageSpeed Insights on at least 5 key pages (mobile and desktop)
  • [ ] Checked Core Web Vitals report in Google Search Console
  • [ ] Ran at least one WebPageTest audit with Mobile 4G settings
  • [ ] Recorded baseline numbers in a spreadsheet or document
  • [ ] Identified whether your biggest issue is LCP, INP, or CLS
  • [ ] Installed the Chrome Web Vitals extension for ongoing monitoring
  • [ ] Understand the difference between field data and lab data

Chapter Exercise

Open PageSpeed Insights and test your highest-traffic blog post on mobile. Look at the “Diagnostics” section and find the top 3 opportunities listed. Write them down:

  • Opportunity 1: (estimated savings: )
  • Opportunity 2: (estimated savings: )
  • Opportunity 3: (estimated savings: )

Now open Chrome DevTools on the same page. Go to the Performance tab, click “Record” and reload the page. Find the Largest Contentful Paint marker in the timeline. What element is your LCP? Write it down:

  • LCP element: ___
  • LCP time: ___

Knowing what your LCP element is tells you exactly where to focus your optimization efforts. If it’s an image, Chapter 5 will fix it. If it’s a text block and the delay is from TTFB, Chapter 3 is your priority. If it’s slow because of render-blocking CSS, Chapter 4’s stack recommendations will help.

Disclaimer: This site is reader-supported. If you buy through some links, I may earn a small commission at no extra cost to you. I only recommend tools I trust and would use myself. Your support helps keep gauravtiwari.org free and focused on real-world advice. Thanks. - Gaurav Tiwari