---
title: "Core Web Vitals in Nuxt"
description: "Measure and optimize LCP, INP, and CLS in Nuxt apps to improve user experience and search rankings in 2026."
canonical_url: "https://nuxtseo.com/learn-seo/nuxt/launch-and-listen/core-web-vitals"
last_updated: "2026-01-29"
---

<key-takeaways>

- LCP ≤2.5s, INP ≤200ms, CLS ≤0.1 are the thresholds. 75% of visits must pass for "Good" status
- **INP** is the primary interactivity metric in 2026. Focus on yielding the main thread
- Use `@nuxt/image` with `priority` prop for above-fold images, `loading="lazy"` for below-fold
- Test with **CPU Throttling** (4x or 6x) in DevTools to simulate real-world mobile performance

</key-takeaways>

[Core Web Vitals](https://developers.google.com/search/docs/appearance/core-web-vitals) are a critical Google ranking factor. They measure loading performance, interactivity, and visual stability. In 2026, passing these metrics is essential for visibility in both traditional search and AI Overviews.

## The Three Metrics

### LCP (Largest Contentful Paint)

LCP measures how long it takes for the largest visible element to render. This is typically a hero image, heading, or large text block.

**Thresholds:**

- Good: ≤ 2.5 seconds
- Needs improvement: 2.5–4.0 seconds
- Poor: > 4.0 seconds

### INP (Interaction to Next Paint)

INP measures responsiveness throughout the entire page session. It replaced FID in March 2024. A good INP score ensures that the browser can provide visual feedback quickly after any user interaction (click, tap, keypress).

**Thresholds:**

- Good: ≤ 200 milliseconds
- Needs improvement: 200–500 milliseconds
- Poor: > 500 milliseconds

### CLS (Cumulative Layout Shift)

CLS measures visual stability. Every unexpected layout shift gets scored: images loading without dimensions, fonts causing text reflow, dynamic content insertion.

**Thresholds:**

- Good: ≤ 0.1
- Needs improvement: 0.1–0.25
- Poor: > 0.25

## Nuxt LCP Optimizations

### SSR by Default

Nuxt [renders pages on the server](/learn-seo/nuxt/routes-and-rendering/rendering) by default, which significantly improves LCP compared to client-side rendering. The browser receives fully rendered HTML, eliminating the wait for JavaScript execution before content appears.

### Image Optimization with @nuxt/image

Install the Nuxt Image module for automatic image optimization:

```bash
npx nuxi@latest module add image
```

Use `<NuxtImg>` and `<NuxtPicture>` for optimized delivery:

```vue
<template>
  <div>
    <!-- Above-fold: prioritize LCP image -->
    <NuxtImg
      src="/hero.jpg"
      alt="Hero"
      width="1200"
      height="600"
      priority
    />

    <!-- Below-fold: lazy loading -->
    <NuxtImg
      src="/product-1.jpg"
      alt="Product"
      width="800"
      height="600"
      loading="lazy"
    />
  </div>
</template>
```

The `priority` prop preloads the LCP image and disables lazy loading.

### Preload Critical Assets

Add preload hints in your page or layout:

```vue
<script setup lang="ts">
useHead({
  link: [
    {
      rel: 'preload',
      href: '/fonts/inter-var.woff2',
      as: 'font',
      type: 'font/woff2',
      crossorigin: ''
    }
  ]
})
</script>
```

## Nuxt INP Optimizations (Advanced)

In 2026, INP is often the hardest metric to pass. Long JavaScript tasks block the main thread, causing delayed feedback.

### Yield to the Browser

Break up long tasks to allow the browser to paint updates between computations.

**Using scheduler.yield() (Modern Browsers):**

```ts
async function handleComplexInteraction() {
  // Step 1: Immediate feedback
  showLoadingState()

  // Yield to allow the browser to paint the loading state
  await scheduler.yield()

  // Step 2: Heavy computation
  performHeavyWork()
}
```

**Using scheduler.postTask():**

```ts
function handleInteraction() {
  // Schedule non-critical work with lower priority
  scheduler.postTask(() => {
    trackAnalytics()
    syncDataInBackground()
  }, { priority: 'background' })
}
```

### Debounce Event Handlers

Prevent performance issues from rapid-fire events:

```vue
<script setup lang="ts">
import { useDebounceFn } from '@vueuse/core'
import { ref } from 'vue'

const searchQuery = ref('')

const handleSearch = useDebounceFn((val) => {
  searchQuery.value = val
  // Perform search
}, 300)
</script>

<template>
  <input placeholder="Search..." @input="e => handleSearch(e.target.value)">
</template>
```

### Optimize Vue Reactivity

Avoid deep reactivity on large data objects which can cause long processing times during updates:

```ts
// Nuxt 3.12+ / 4.0 optimization
const { data } = await useAsyncData('products', () => $fetch('/api/products'), {
  deep: false // Disable deep reactivity for large payloads
})
```

## Nuxt CLS Fixes

### Set Image Dimensions

Always provide `width` and `height` to reserve space before the image loads:

```vue
<template>
  <NuxtImg
    src="/product.jpg"
    alt="Product"
    width="800"
    height="600"
  />
</template>
```

### Reserve Space for Dynamic Content

Use skeleton screens that match the dimensions of the final content:

```vue
<template>
  <div class="content">
    <div v-if="pending" class="skeleton h-[200px] w-full" />
    <div v-else class="h-[200px] w-full">
      {{ data }}
    </div>
  </div>
</template>
```

## Measuring Core Web Vitals

### PageSpeed Insights & RUM

[PageSpeed Insights](https://pagespeed.web.dev/) shows field data (real user metrics). For 2026, supplement this with **Real User Monitoring (RUM)** tools like Vercel Speed Insights, Datadog, or [RUMvision](https://www.rumvision.com/).

### Advanced DevTools Debugging

To find the cause of a poor INP score:

1. Open DevTools → **Performance** tab
2. Set **CPU Throttling** to **4x slowdown** (to simulate a mid-range mobile device)
3. Click **Record**
4. Perform the interaction (e.g., click a button)
5. Stop recording and look for the **Interactions** track
6. Expand the slow interaction to see the breakdown: **Input Delay**, **Processing Duration**, and **Presentation Delay**

[Breaking long tasks](https://web.dev/articles/optimize-long-tasks) into chunks under 50ms is the key to a "Good" INP.

## Core Web Vitals Impact on Rankings

Google treats Core Web Vitals as a [tiebreaker ranking factor](https://developers.google.com/search/docs/appearance/core-web-vitals). Content relevance is still primary, but for competitive queries, good page experience is the differentiator.

[Mobile-first indexing](https://developers.google.com/search/docs/crawling-indexing/mobile/mobile-first-indexing) now treats Core Web Vitals as indexing requirements rather than just ranking signals for some query types.

To pass assessment, [75% of page visits](https://web.dev/articles/defining-core-web-vitals-thresholds) must meet "Good" thresholds.
