Skip to main content
Web Development

Optimizing Core Web Vitals: A Technical Guide

Roger M.March 12, 20265 min read

Core Web Vitals are Google ranking factors. Poor scores mean lower rankings. This guide shows you how to systematically improve LCP, INP, and CLS.

The Three Core Web Vitals

LCP (Largest Contentful Paint)

What it measures: How quickly the largest visible element loads.

Target value: under 2.5 seconds

Most common problems and solutions:

  • Large images: Use loading="lazy" and modern formats (WebP, AVIF)
  • Render-blocking resources: Load CSS and JS asynchronously
  • Slow server: Use a CDN, optimize server response time
  • Client-side rendering: Use prerendering for static content

INP (Interaction to Next Paint)

What it measures: How quickly the page responds to user interactions.

Target value: under 200 milliseconds

Most common problems and solutions:

  • Long JavaScript tasks: Code splitting with React.lazy() and Suspense
  • Heavy event handlers: Use requestAnimationFrame or requestIdleCallback
  • Excessive re-renders: Use React.memo(), useMemo(), useCallback()

CLS (Cumulative Layout Shift)

What it measures: How stable the layout remains during loading.

Target value: under 0.1

Most common problems and solutions:

  • Images without dimensions: Always specify width and height
  • Web fonts: font-display: swap and font preloading
  • Dynamic content: Use placeholders with fixed dimensions
  • Ads and embeds: Define reserved space

Measuring and Monitoring

web-vitals Library

The simplest method for measurement:

import { onCLS, onINP, onLCP } from 'web-vitals'

function sendToAnalytics(metric) {
  gtag('event', metric.name, {
    value: Math.round(metric.value),
    event_category: 'Web Vitals',
    event_label: metric.id,
  })
}

onCLS(sendToAnalytics)
onINP(sendToAnalytics)
onLCP(sendToAnalytics)

Google Search Console

The Core Web Vitals Report in Search Console shows aggregated data from your real users. Check it regularly.

Chrome DevTools

In the Performance Tab, you can analyze individual metrics in detail. Particularly useful for diagnosing INP issues.

React-Specific Optimizations

Lazy Loading with Code Splitting

const HeavyComponent = lazy(() => import('./HeavyComponent'))

function App() {
  return (
    <Suspense fallback={<Skeleton />}>
      <HeavyComponent />
    </Suspense>
  )
}

Prerendering for SEO

Single-page apps inherently have poor LCP scores since the browser must first load and execute JavaScript. Build-time prerendering solves this problem:

  1. Vite builds the app
  2. Playwright visits each route
  3. The rendered HTML is saved as a static file
  4. Search engines immediately receive the finished content

Image Optimization

<img
  src="/hero.webp"
  alt="Hero image"
  width={1200}
  height={630}
  loading="lazy"
  decoding="async"
/>

For above-the-fold images: loading="eager" and fetchPriority="high".

Checklist

  • [ ] LCP under 2.5s for all important pages
  • [ ] INP under 200ms (test with real interactions)
  • [ ] CLS under 0.1 (especially check on mobile)
  • [ ] Images in WebP/AVIF with explicit dimensions
  • [ ] Fonts preloaded with font-display: swap
  • [ ] JavaScript bundle under 200 KB (gzipped)
  • [ ] web-vitals library installed and connected to analytics
  • [ ] Regular review in Search Console

Conclusion

Core Web Vitals are not a one-time project but an ongoing process. Measure regularly, set priorities based on data, and optimize step by step. The biggest gains are almost always achieved with images and JavaScript bundle size.

predivo

Software that thinks ahead.

Legal

© 2026 Predivo GmbH

Küssnacht, Switzerland