← Chrome 151 reference

v151 · web api · shipped

PerformanceSoftNavigation and InteractionContentfulPaint performance entry

New PerformanceEntry types that let you measure Core Web Vitals — LCP, CLS, INP — for single-page application navigations that happen without a full page reload.

at a glance

Shipped inChrome 151 (desktop, Android, WebView; enabled by default)
StatusEnabled by default (Finch SoftNavigationHeuristics)
Origin trialChrome 139–149 (extended across 3 rounds); stable ship in Chrome 151
SpecSoft Navigations — WICG
ExplainerWICG / soft-navigations
ChromeStatus5144837209194496 — PerformanceSoftNavigation and InteractionContentfulPaint performance entry
Source: chromestatus.com/feature/5144837209194496; ChromeStatus API record; milestone 151 features

Implementation-status divergence, both sides reported rather than resolved (fetched 2026-10-07): this page records PerformanceSoftNavigation and InteractionContentfulPaint shipping enabled by default in Chrome 151 per active ship stage 160 (desktop_first: 151, android_first: 151, webview_first: 151) and the blink-dev Intent to Ship. In contrast, the ChromeStatus API record top-level status string still lists status as “Origin trial” with milestone 151, reflecting the final experimental OT extension through milestone 149 before general availability.

why it exists

Single-page applications (SPAs) have always been invisible to the Core Web Vitals (CWV) framework. CWV metrics like Largest Contentful Paint, Cumulative Layout Shift, and Interaction to Next Paint are defined relative to a navigation, and traditional navigation timing only fires on full page loads. When a React Router, Next.js, or SvelteKit app pushes a new URL and re-renders in-place, the browser saw no navigation — so no fresh CWV measurement was started. This meant a whole class of web experiences had no performance signal in Search Console, PageSpeed Insights, or field data.

Soft navigations defines a heuristic: if the user interacts (click, keyboard, etc.), the URL changes via History API or Navigation API, and significant DOM updates follow, the browser records a soft-navigation entry and resets the CWV baseline for that navigation scope.

Source: WICG soft-navigations explainer; Chrome developer docs; W3C Performance Timeline

shape of the API and interface definitions

Two new entry types are added to the Performance Timeline per the WICG Soft Navigations specification. Both are observed via the standard PerformanceObserver interface in window environments.

soft-navigation entry

Reported once per detected soft navigation. Extends PerformanceEntry.

entryType"soft-navigation"
nameThe URL string of the destination (after pushState, replaceState, or Navigation API)
startTimeTime of the user interaction that triggered the navigation (hardware event timestamp)
durationTime from interaction until the browser considers the soft navigation rendering complete
navigationIdA unique UUID string grouping all performance entries belonging to this soft navigation

interaction-contentful-paint entry

Analogous to largest-contentful-paint but scoped to a user interaction or soft navigation. Extends PerformanceEntry.

entryType"interaction-contentful-paint"
renderTimeTimestamp when the largest candidate element painted after the interaction
sizeSize in pixels of the candidate painted element
elementReference to the painted DOM Element node
navigationIdLinks to the triggering soft-navigation entry UUID

navigationId on existing entries

All existing PerformanceEntry instances gain a navigationId property. During the initial hard document load, its value matches the initial document navigation ID. After each soft navigation, subsequent entries (such as layout-shift or largest-contentful-paint) carry the new soft navigation's ID.

Attempting to call observe() with invalid observer options or unsupported entry types will throw a TypeError per Performance Timeline specifications.

Source: WICG Soft Navigations spec; WICG explainer

examples

Soft navigations and interaction contentful paints can be observed using PerformanceObserver or queried from the performance timeline.

Observe soft navigations:

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    console.log("Soft navigation to:", entry.name);
    console.log("  Started:", entry.startTime);
    console.log("  Navigation ID:", entry.navigationId);
  }
}).observe({ type: "soft-navigation", buffered: true });

Measure per-navigation LCP and ICP:

const lcpByNav = new Map();

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    // Attribute to the current navigation scope.
    lcpByNav.set(entry.navigationId, entry.renderTime || entry.loadTime);
  }
}).observe({ type: "largest-contentful-paint", buffered: true });

// interaction-contentful-paint gives ICP for soft navigations:
new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    lcpByNav.set(entry.navigationId, entry.renderTime);
    console.log("ICP after soft nav:", entry.navigationId, entry.renderTime);
  }
}).observe({ type: "interaction-contentful-paint", buffered: true });

Slice CLS per navigation:

const clsByNav = new Map();

new PerformanceObserver((list) => {
  for (const entry of list.getEntries()) {
    if (entry.hadRecentInput) continue;
    const id = entry.navigationId;  // new in Chrome 151
    const prev = clsByNav.get(id) ?? 0;
    clsByNav.set(id, prev + entry.value);
  }
}).observe({ type: "layout-shift", buffered: true });

reading buffered entries

You can also query buffered entries synchronously from the performance timeline:

// All soft navigations recorded so far:
const softNavs = performance.getEntriesByType("soft-navigation");

// All ICP entries:
const icpEntries = performance.getEntriesByType("interaction-contentful-paint");

browser support

BrowserStatusNotes
Chrome (Desktop & Android)Chrome 151+Enabled by default (Finch SoftNavigationHeuristics)
EdgeEdge 151+Chromium mirror
FirefoxNo signalTracked in Mozilla standards-positions #854
SafariClosed without positionTracked in WebKit standards-positions #235
Source: chromestatus.com feature 5144837209194496; WPT results

see also