Core Web Vitals: LCP, INP, CLS

Meet the three Core Web Vitals that measure real-world page experience.

Core Web Vitals are Google's set of user-experience metrics. They are part of the page-experience signals and measure how a real page feels to load and use.

Core Web Vitals metrics along a page load timelinetime since page starts loadingLCPlargest content paintedgood < 2.5sINPinteraction responsegood < 200msCLSlayout stabilitygood < 0.1
The three Core Web Vitals measure loading, interactivity and visual stability.

The three metrics

  • LCP - Largest Contentful Paint: how long until the main content appears. Good is under 2.5s.
  • INP - Interaction to Next Paint: how quickly the page responds to input. Good is under 200ms. (INP replaced FID in 2024.)
  • CLS - Cumulative Layout Shift: how much the layout jumps around. Good is under 0.1.

Field vs lab data

Google ranks on field data from real users (the Chrome UX Report). Lab tools like Lighthouse help you diagnose, but the field numbers are what count.

Example

Example · bash
# Core Web Vitals "good" thresholds
LCP  (loading)        < 2.5 s
INP  (interactivity)  < 200 ms
CLS  (visual stability)< 0.1

When to use it

  • An e-commerce site fixes its LCP from 5.2 s to 1.8 s by preloading the hero image, regaining first-page rankings on several competitive product keywords.
  • A news publisher eliminates CLS caused by late-loading ad slots by reserving fixed-height containers, removing a ranking penalty for poor page experience.
  • A SaaS landing page reduces INP from 420 ms to 180 ms by deferring heavy analytics scripts, crossing into the 'Good' threshold for all three Core Web Vitals.

More examples

Preload LCP hero image

Preloading the LCP image with fetchpriority=high tells the browser to fetch it before parsing the rest of the document, directly reducing LCP time.

Example · html
<head>
  <!-- Preload the largest image in the initial viewport to improve LCP -->
  <link rel="preload" as="image"
        href="/images/hero-800.webp"
        imagesrcset="/images/hero-400.webp 400w,
                     /images/hero-800.webp 800w"
        imagesizes="(max-width:600px) 400px, 800px">
</head>
<body>
  <img src="/images/hero-800.webp"
       srcset="/images/hero-400.webp 400w, /images/hero-800.webp 800w"
       sizes="(max-width:600px) 400px, 800px"
       alt="Hero product shot"
       fetchpriority="high">  
</body>

Reserve space to prevent CLS

Reserving dimensions for ads and images prevents layout shifts that accumulate into a high CLS score, which Google uses as a page-experience ranking factor.

Example · html
<style>
  /* Reserve height for ad slot before it loads — prevents layout shift */
  .ad-banner {
    min-height: 90px;   /* matches the expected ad height */
    width: 728px;
    background: #f5f5f5; /* placeholder colour */
  }
  /* Always set explicit width/height on images to prevent reflow */
  .product-img { width: 400px; height: 400px; object-fit: cover; }
</style>
<div class="ad-banner"></div>
<img class="product-img" src="/shoe.jpg" alt="Trail Runner Pro">

Measure CWV with CrUX API

The CrUX API returns 75th-percentile field data for all three Core Web Vitals — the exact values Google uses when applying the page-experience ranking signal.

Example · bash
curl -s -X POST \
  "https://chromeuxreport.googleapis.com/v1/records:queryRecord?key=YOUR_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "url": "https://example.com/",
    "metrics": [
      "largest_contentful_paint",
      "interaction_to_next_paint",
      "cumulative_layout_shift"
    ]
  }' | python3 -c "
import sys, json
for metric, data in json.load(sys.stdin).get('record',{}).get('metrics',{}).items():
    p75 = data.get('percentiles',{}).get('p75')
    print(f'{metric}: p75={p75}')
"

Discussion

  • Be the first to comment on this lesson.