If you want to improve the performance of a website, the first question is always the same: What exactly should we measure?

Core Web Vitals answer that question with three metrics focused on loading, stability, and responsiveness. These metrics (Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint) represent Google’s framework for quantifying user experience. They directly influence search rankings, user satisfaction, conversion rates, and ultimately, your bottom line.

As of 2026, the landscape has evolved significantly. INP has fully replaced First Input Delay (FID) as the responsiveness metric, and Core Web Vitals are now assessed holistically at the site-wide level rather than per page. Slow pages anywhere on your site can suppress rankings for every page, making optimization more critical than ever.

In this guide, we walk through each metric, explore what is actually happening inside the browser, examine common pitfalls, and provide actionable strategies to achieve and maintain passing scores.


Understanding Core Web Vitals

Core Web Vitals focus on three aspects of user experience:

  • Largest Contentful Paint (LCP) — measures how quickly the main content appears (loading).
  • Cumulative Layout Shift (CLS) — measures how stable the page layout is (visual stability).
  • Interaction to Next Paint (INP) — measures how responsive the page feels when users interact with it (responsiveness).
Key concept

For a page to pass Core Web Vitals, all three metrics must be in the “good” range for at least 75% of visits. A single weak metric can cause a page to fail entirely, even if the other two are excellent.


Largest Contentful Paint (LCP) — Loading Performance

What Is LCP?

LCP measures the time it takes for the largest visible element in the viewport to finish rendering. Usually, this element is something like a hero image, a large heading, or the main content block.

Instead of asking “when did the page start loading?”, LCP asks a more meaningful question: “When does the main content actually appear for the user?”

How the Browser Calculates LCP

As the page loads, different elements start appearing inside the viewport:

LCP calculation flow

A small element appears: the browser treats it as the current LCP candidate.

A larger element appears: the browser updates the candidate.

The largest element appears: once rendering finishes, the browser records the LCP time.

LCP is essentially the moment when the largest visible element finished painting in the viewport.

LCP Thresholds (2026)

CategoryLCP TimeStatus
Good≤ 2.5 secondsPassing
Needs Improvement2.6–4.0 secondsWarning
Poor> 4.0 secondsFailing
Note

At least 75% of page loads must meet the “good” threshold based on real-world (field) data from the Chrome User Experience Report (CrUX).

The Four Sub-parts of LCP

Understanding LCP breakdown helps pinpoint exactly where optimization efforts should focus.

Sub-partWhat It MeasuresTypical Target
Time to First Byte (TTFB)Time from page load start to receiving the first byte of HTML≤ 200ms
Resource Load DelayTime from TTFB to when browser starts loading the LCP resourceMinimize
Resource Load DurationTime to fully load the LCP resourceDepends on file size
Element Render DelayTime from resource load completion to full rendering of LCP elementMinimize

Ideally, most LCP time should be spent on loading resources, not on delays caused by render-blocking scripts or slow server responses.

Common LCP Pitfalls

Render-Blocking JavaScript

The Problem: A slow JavaScript file is loaded in the <head>. Because scripts can modify the DOM, the browser must stop parsing HTML while the script downloads and executes. The browser cannot reach the part of the HTML where the hero image appears, so the image request starts only after the script finishes. LCP becomes significantly worse.

The Solution: Use defer on scripts that do not need to run immediately. This allows the browser to continue parsing HTML, build the DOM, and download scripts in parallel. The script executes only after HTML parsing is finished.

<script src="https://webkeepy.com/js/bundle.js" defer></script>

Missing Preload Hints

The Problem: The browser discovers the LCP element too late in the HTML, so resource loading begins later than necessary.

The Solution: Preload the hero image with <link rel="preload"> in the <head> and set fetchpriority="high".

<link rel="preload" as="image" href="https://webkeepy.com/hero.avif" fetchpriority="high">

Uncompressed Images

The Problem: Large image files take too long to download (for example, a 2.4 MB hero image).

The Solution: Convert images to WebP or AVIF (30–50% smaller than JPEG), use responsive srcset with breakpoints, and apply loading="eager" and fetchpriority="high" to the LCP element.

LCP Optimization Checklist

  • Ensure TTFB is under 200ms.
  • Use static generation (SSG) where possible; pre-rendered HTML beats any server-side solution.
  • Implement CDN caching with stale-while-revalidate headers.
  • Eliminate render-blocking resources (use defer or async).
  • Preload the LCP element.
  • Use modern image formats (AVIF, WebP).
  • Set appropriate dimensions and fetchpriority.
  • Ensure the LCP resource is discoverable from the HTML source.
Real-world impact

An e-commerce client reduced LCP from 4.8 seconds to 1.9 seconds by switching from PNG to AVIF, preloading the hero image, moving to static generation, and using fetchpriority="high". Organic traffic increased by 23% within eight weeks.


Cumulative Layout Shift (CLS) — Visual Stability

What Is CLS?

CLS measures how much visible content moves unexpectedly while the page is loading. You have probably experienced this: you start reading something on a page, and suddenly the text jumps because an image loads above it or an advertisement suddenly appears. Each of those moments creates a layout shift. CLS adds up all these shifts into a single score.

How the Browser Calculates CLS

Imagine a simple grid layout with several elements:

CLS calculation process

Everything looks stable initially.

One element suddenly grows (for example, because an image loads and its size was not known).

Surrounding elements move to make space. This movement creates a layout shift.

Each shift moment contributes to the CLS score.

CLS Thresholds

CategoryCLS ScoreStatus
Good≤ 0.1Passing
Needs Improvement0.1–0.25Warning
Poor> 0.25Failing

Unlike LCP and INP, CLS is not measured in seconds or milliseconds; it is a unitless score based on how much content shifts and by how far.

Lab Data vs. Field Data for CLS

A common misconception is that lab tools (Lighthouse) and field data (CrUX) should show identical CLS scores. They often do not, and that is expected.

  • Lab tools (Lighthouse) typically measure only the initial page load.
  • CrUX (field data) measures CLS throughout the full lifecycle of the page.
  • Layout shifts can happen after initial load (for example, lazy-loaded content shifting as users scroll).
  • Shifts occurring within 500ms of a user interaction are excluded from CLS (considered expected shifts).
Diagnostic tip

If PageSpeed Insights shows a difference between CrUX CLS and Lighthouse CLS, the discrepancy is likely due to post-load CLS issues (such as shifts that happen after scrolling).

Common CLS Pitfalls

Images Without Dimensions

The Problem: Images do not specify width and height attributes. The browser does not know how much space the image will occupy, so it reserves no space. When images finally load, the browser suddenly inserts them into the layout, and the rest of the page shifts downward.

The Solution: Always add width and height attributes to image elements. The browser can calculate the correct aspect ratio and reserve space immediately. Even before images finish loading, the layout knows how much space they need.

<img src="https://webkeepy.com/product.jpg" width="800" height="600" alt="Product">

Dynamic Content Injection

The Problem: Ads, banners, or pop-ups are inserted above existing content, causing everything below to shift down unexpectedly.

The Solution: Reserve space for ads, embeds, and iframes before they load. Never insert content above content that has already rendered. Avoid injecting dynamic content (banners, pop-ups) at the top of the page after main content loads.

Web Fonts (FOUT/FOIT)

The Problem: Text reflows when web fonts load or fail to load. Invisible text (FOIT) or swapped text (FOUT) causes layout shifts.

The Solution: Use font-display: swap so text paints immediately. Consider using size-adjust to reduce Flash of Unstyled Text (FOUT).

CLS Optimization Checklist

  • Add width and height attributes to all images and videos.
  • Use CSS aspect-ratio for dynamic media.
  • Reserve space for ads, embeds, and iframes before they load.
  • Never inject content above already-rendered content.
  • Use font-display: swap for web fonts.
  • Avoid inserting dynamic banners or pop-ups at the top of the page.

Interaction to Next Paint (INP) — Responsiveness

What Is INP?

INP measures how quickly the page responds to user input (clicks, key presses, or taps on the screen). When a user interacts with your page, the browser should update the interface quickly so the user feels the action was recognized.

INP is the time between the user interaction and the next visual update on the screen.

Why INP Replaced FID

MetricWhat It MeasuredLimitation
FID (First Input Delay)Only the first interactionFailed to capture slow interactions that occurred later in the session
INP (Interaction to Next Paint)The worst interaction during the entire page visitCaptures the full user experience more accurately
Key insight

If a user clicks a button after 30 seconds and the main thread is blocked by a heavy JavaScript bundle, FID would not catch it, but INP would, because it measures the worst interaction, not just the first one.

How INP Is Calculated

INP has three sub-parts:

Sub-partDescription
Input DelayFrom user interaction start to when the event callback begins running
Processing DurationTime for the event callback to complete
Presentation DelayTime from callback completion to the next paint (visual update)

INP Thresholds

CategoryINP TimeStatus
Good≤ 200 millisecondsPassing
Needs Improvement200–500msWarning
Poor> 500msFailing

Common INP Pitfalls

Heavy Processing on the Main Thread

The Problem: A button triggers heavy work. Because JavaScript is single-threaded in the browser, this work blocks everything else. The browser cannot update the UI and cannot respond to other interactions. The user clicks and nothing appears to happen until the computation finishes. Only then does the page update. The result is a slow and unresponsive experience (poor INP).

The Solution: Instead of doing all the work at once, break the task into smaller chunks. When the button is clicked, immediately update the UI to show something like “processing”. Process a small portion of the work, then yield control back to the browser. This can be done using techniques like setTimeout or chunked loops. Because you periodically yield control, the browser can repaint the UI and respond to other interactions. Users see immediate feedback, and the page remains responsive.

// Example: chunked processing
function processChunk(data, index, chunkSize) {
  const chunk = data.slice(index, index + chunkSize);
  // process chunk
  if (index + chunkSize < data.length) {
    setTimeout(() => processChunk(data, index + chunkSize, chunkSize), 0);
  }
}

Long Tasks (over 50ms)

The Problem: Any task that runs for more than 50ms on the main thread is a “long task”. Long tasks block the browser from handling user interactions and updating the UI.

The Solution: Break long tasks using scheduler.yield() or requestIdleCallback. Use setTimeout to split work into smaller chunks.

Heavy JavaScript Bundles

The Problem: Loading too much JavaScript on the initial page load. A single slow third-party script can push an otherwise clean site into “needs improvement” territory.

The Solution: Use code splitting to load only the JavaScript needed for the current page. Defer or delay non-critical third-party scripts (analytics, ads, chat widgets). Push non-urgent work into Web Workers when possible.

Inefficient Event Handlers

The Problem: Expensive event handlers running on every interaction.

The Solution: Debounce expensive event handlers. Use useTransition for non-urgent state updates in React. Push non-urgent work to the background.

INP Optimization Checklist

  • Break long tasks (> 50ms) using scheduler.yield() or chunked processing.
  • Implement code splitting to reduce initial JavaScript payload.
  • Defer or delay non-critical third-party scripts.
  • Debounce expensive event handlers.
  • Use requestIdleCallback for non-urgent work.
  • Move heavy processing to Web Workers where possible.

Measuring Core Web Vitals

Lab Data vs. Field Data

TypeToolsWhat It MeasuresBest For
Lab DataPageSpeed Insights, Lighthouse, WebPageTestSimulated page loads in controlled conditionsDiagnosing issues and testing fixes
Field Data (RUM)CrUX (Chrome User Experience Report), Search ConsoleActual user experiencesUnderstanding real-world performance (what Google uses for ranking)
Key insight

Field data, not lab tools, is what Google uses to judge real-world experience. Always prioritize field data when evaluating Core Web Vitals.

Recommended Tools

ToolData TypeBest Used For
Google Search Console → Experience → Core Web VitalsField data (CrUX)Monitoring overall site health
PageSpeed InsightsLab + Field (CrUX)Detailed breakdown of scores and opportunities
Chrome DevTools → Performance panelLab dataLocal testing with live metrics
Web Vitals Library (JavaScript)Field data (RUM)Measuring real user experience programmatically

The State of Core Web Vitals in 2026

Current Thresholds (Unchanged)

MetricGood Threshold2026 Status
LCP≤ 2.5 secondsThreshold unchanged
CLS≤ 0.1Threshold unchanged
INP≤ 200 millisecondsReplaced FID in 2024; measurement methodology refined in 2026

The Harsh Reality

As of the May 2026 CrUX release

  • Only 55.9% of tracked origins pass all three Core Web Vitals simultaneously.
  • Individual pass rates are higher: LCP ~68.6%, CLS ~81.3%, INP ~86.6%.
  • Most sites fail because of one weak metric dragging down two strong ones.

2026 Measurement Changes

  1. INP Methodology Refined: Better captures sustained interaction latency on input-heavy pages.
  2. Site-Wide Assessment: Core Web Vitals are now evaluated at the site level; slow pages anywhere can suppress rankings for every page.
  3. At Least 75% of Visits: Passing requires 75% of page loads to meet thresholds in field data.

The Core Principles

Improving Core Web Vitals is really about a few simple ideas:

  1. Prioritize important resources. Make sure the most important content appears as early as possible. Preload critical resources. Do not let JavaScript block the browser from loading important elements.
  2. Keep the layout predictable. Reserve space for images and dynamic content. Always specify dimensions for media. Do not inject content above already-rendered content.
  3. Keep the main thread free. Avoid long blocking work on the main thread. Break heavy tasks into smaller chunks. Defer non-critical scripts.
  4. Measure with field data. What matters is real user experience, not just lab tests. Use CrUX and Search Console to monitor your actual scores.

Final Takeaways

MetricWhat It MeasuresKey Action
LCPLoading speedEliminate render-blocking resources; preload critical images; optimize server response
CLSVisual stabilityReserve space for all dynamic content; specify dimensions on images
INPResponsivenessBreak long tasks; optimize event handlers; defer non-critical scripts
The formula for success

All three vitals must pass simultaneously. One weak metric can cause your entire page to fail Core Web Vitals. Prioritize performance holistically, not just for individual metrics.


Additional Resources

  • Run the demo project locally to test before and after versions.
  • Check out detailed guides on preload, prefetch, and lazy loading.
  • Explore front-end system design courses for deeper understanding of performance and architecture.