Article

How to Fix Core Web Vitals in Next.js (LCP + CLS + TTI)

·5 min read min read·👁 10
Dharmendra Singh Yadav

Dharmendra Singh Yadav

Founder, Dharmsy Innovations

How to Fix Core Web Vitals in Next.js (LCP + CLS + TTI)

Core Web Vitals are one of the most important ranking factors for Google in 2025.

If your Next.js website is slow or unstable, you’ll see warnings like:

  1. Poor LCP (Largest Contentful Paint)
  2. CLS (Cumulative Layout Shift)
  3. TTI (Time to Interactive)

The good news?

Next.js gives you everything needed to fix these — if you structure your app correctly.

Let’s break down what causes bad Web Vitals and how to fix them step-by-step in a simple, human way.

⭐ What Are Core Web Vitals?

1. LCP – Largest Contentful Paint

How fast your biggest element loads (hero image, heading, banner).

2. CLS – Cumulative Layout Shift

Does your layout jump when loading? (fonts, ads, images, dynamic content)

3. TTI – Time to Interactive

How fast the page becomes usable (JS hydration, heavy scripts, client components)

🚨 Why Next.js Sites Fail Core Web Vitals

Common issues:

  1. Using Client Components everywhere
  2. Large or unoptimized hero images
  3. Not using next/image
  4. Layout shifts from missing width/height
  5. Loading fonts incorrectly
  6. Heavy JS from UI libraries
  7. Not using streaming or Server Components
  8. Hydration issues from dynamic imports

Let’s fix each one.

✅ 1. Fix LCP (Largest Contentful Paint)

Problem: Hero image loads too late or too large.

Solution 1: Use next/image always

import Image from "next/image";

<Image
src="/hero.png"
width={1200}
height={600}
priority
alt="Hero Image"
/>

Why this works:

  1. priority forces the image to load early
  2. Correct width/height prevents CLS
  3. Next.js automatically optimizes formats (WebP, AVIF)

Solution 2: Move heavy React code to Server Components

// This runs on the server, not blocking the browser
export default function HomePage() {
return (
<main>
<HeroSection /> {/* server component */}
<Features />
</main>
);
}

Server Components reduce JS shipped to the browser → faster LCP.

Solution 3: Remove large blocking scripts

  1. Remove unused analytics
  2. Move scripts to afterInteractive
<Script src="..." strategy="afterInteractive" />

Solution 4: Self-host fonts properly

Google Fonts = LCP killer.

Use Next.js built-in font optimizer:

import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'], display: 'swap' })

This eliminates render-blocking font loads.

✅ 2. Fix CLS (Cumulative Layout Shift)

Problem: Layout moves around during load.

Common causes:

  1. Images without width/height
  2. Loading ads/widgets dynamically
  3. Late-loading fonts
  4. Sticky header shifting on scroll
  5. Carousels without fixed size

Let’s fix.

Solution 1: Give all images fixed size

Never use images like this ❌

<img src="/banner.jpg" />

Always use ❌ width + height OR fill:

<Image
src="/banner.jpg"
alt="Banner"
width={1600}
height={800}
priority
/>

Solution 2: Reserve space for dynamic sections

If an element loads late (chat widget, ads), reserve space:

.placeholder {
min-height: 300px;
}

Solution 3: Fix layout shift from fonts

Use:

const inter = Inter({ subsets: ['latin'], display: 'swap' });

“swap” avoids invisible text → big CLS fix.

Solution 4: Don’t animate layout during hydration

Example bad:

<div className={clientLoaded ? "visible" : "hidden"}>

Better:

<div suppressHydrationWarning>

or manage animations after mount.

Solution 5: Use stable header height

Your header should not change size when scrolled.

Use:

header {
height: 80px;
}

✅ 3. Fix TTI (Time to Interactive)

Problem: Page loads but buttons don’t work instantly.

This happens when:

  1. Too many Client Components
  2. Heavy JavaScript
  3. Large UI libraries being loaded
  4. Hydration takes long
  5. Dynamic imports used incorrectly

Solution 1: Convert more components to Server Components

Wrong ❌ (everything client):


"use client"
import Hero from "@/components/Hero"
import Features from "@/components/Features"

Correct ✅:

// server by default
import Hero from "@/components/Hero"
import Features from "@/components/Features"

Only interactive components should use "use client":

"use client";
export function ContactForm() { ... }

Your TTI will instantly improve because less JS = faster interactivity.

Solution 2: Use dynamic imports

Instead of loading everything:

import HeavyChart from "@/components/HeavyChart";

Load only when needed:

const HeavyChart = dynamic(() => import("@/components/HeavyChart"), {
ssr: false,
loading: () => <p>Loading chart...</p>,
});

Reduces TTI dramatically.

Solution 3: Reduce JavaScript shipped

Avoid:

  1. MUI (heavy)
  2. Full lodash
  3. Big date libraries

Use smaller alternatives:

  1. date-fns
  2. lodash-es tree-shaking
  3. Radix UI instead of MUI

Solution 4: Use React Server Components for data

Old way (slow TTI):

"use client";
useEffect(() => {
fetch("/api/products")
}, []);

New way (fast):

export default async function Page() {
const products = await getProducts(); // server
return <ProductList products={products} />;
}

Zero JS required on the client.

🎯 Bonus: Tools to Debug Web Vitals

1. Chrome Lighthouse / DevTools

Performance → Web Vitals

2. Pagespeed Insights

Excellent lab + field data

3. Next.js built-in analyzer

npm run build && ANALYZE=true next build

4. Web Vitals Logger for production

export function reportWebVitals(metric) {
console.log(metric);
}

Related Guides

Frequently Asked Questions

LCP – Largest Contentful Paint?+

How fast your biggest element loads (hero image, heading, banner).

CLS – Cumulative Layout Shift?+

Does your layout jump when loading? (fonts, ads, images, dynamic content)

TTI – Time to Interactive?+

How fast the page becomes usable (JS hydration, heavy scripts, client components)

What is Chrome Lighthouse / DevTools?+

Performance → Web Vitals

What is Pagespeed Insights?+

Excellent lab + field data

How can Dharmsy help?+

Dharmsy builds production-grade web, mobile, and SaaS products. Share your requirements and we'll give you a clear, honest plan.

Work with Dharmsy Innovations

Turn Your SaaS or App Idea Into a Real Product — Faster & Affordable

Dharmsy Innovations helps founders and businesses turn ideas into production-ready products — from MVP and prototypes to scalable platforms in web, mobile, and AI.

No sales pressure — just honest guidance on cost, timeline & tech stack.