Core Web Vitals Advanced Guide: Fix LCP, INP and CLS Issues

Core Web Vitals as a Ranking Signal in 2026

Core Web Vitals (CWV) remain part of Google’s page experience signals in 2026, comprising three metrics: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS). INP replaced First Input Delay (FID) as the responsiveness metric in March 2024, raising the bar significantly — whilst most sites passed FID thresholds, INP is a far more comprehensive measure of interactivity that many sites still fail.

The ranking impact of Core Web Vitals is real but contextual. Google has consistently described page experience as a tiebreaker rather than a dominant ranking factor. When two pages have comparable content relevance and authority, the one with better Core Web Vitals may rank higher. However, CWV will not override significantly stronger content or backlink profiles.

For Singapore businesses in competitive niches — where multiple sites produce quality content targeting the same keywords — Core Web Vitals become a meaningful differentiator. A site that passes all three CWV thresholds has a structural advantage over competitors that fail one or more metrics. Combined with strong SEO fundamentals, excellent Core Web Vitals contribute to a compounding performance advantage.

The current thresholds for “good” scores are: LCP under 2.5 seconds, INP under 200 milliseconds, and CLS under 0.1. These are measured at the 75th percentile of real user experiences (field data from the Chrome User Experience Report), meaning 75% of your visitors must experience scores within these thresholds for the page to pass.

Advanced LCP Optimisation

Largest Contentful Paint measures how quickly the largest visible content element renders in the viewport. For most pages, this is a hero image, a large text block, or a video poster frame. Advanced LCP optimisation goes beyond basic image compression to address the full rendering pipeline.

Identifying the LCP Element

Before optimising, confirm which element Google measures as your LCP. Use Chrome DevTools Performance panel, Lighthouse, or the Web Vitals JavaScript library to identify the LCP element on each key page template. The LCP element may differ between mobile and desktop viewports — a hero image on desktop might not be the largest element on mobile if the layout reflows.

Server Response Time (TTFB)

LCP cannot be faster than your Time to First Byte. If your server takes 800ms to begin responding, achieving a 2.5-second LCP leaves only 1.7 seconds for everything else — resource loading, parsing, and rendering. For Singapore-hosted sites serving primarily local traffic, target a TTFB under 200ms. Key TTFB improvements include:

  • Server-side caching: Implement full-page caching (Varnish, Redis, Nginx FastCGI cache) for pages that do not require personalisation. A cached response can achieve sub-50ms TTFB.
  • Database optimisation: Slow queries are the primary cause of high TTFB on dynamic sites. Profile queries, add appropriate indices, and implement query caching.
  • Edge computing: Use a CDN with edge computing capabilities (Cloudflare Workers, AWS Lambda@Edge) to generate or cache responses at edge nodes geographically close to your users.

Resource Discovery and Prioritisation

The browser must discover, download, and render the LCP element. Delays in any step increase LCP. Advanced techniques to accelerate resource discovery:

Preload critical resources: Use rel=”preload” for LCP images and fonts. This tells the browser to begin downloading the resource immediately, before the parser encounters it in the HTML.

<link rel="preload" as="image" href="/images/hero.webp" fetchpriority="high">
<link rel="preload" as="font" href="/fonts/heading.woff2" type="font/woff2" crossorigin>

Fetch priority API: The fetchpriority attribute (supported in modern browsers) explicitly signals which resources are most important. Set fetchpriority=”high” on the LCP image and fetchpriority=”low” on below-the-fold images.

<img src="/images/hero.webp" fetchpriority="high" alt="Hero image" width="1200" height="600">

Avoid lazy loading the LCP image: A common mistake is applying loading=”lazy” to all images, including the hero image. Lazy-loaded images wait until they enter the viewport before loading, which adds unnecessary delay for above-the-fold content. The LCP image should load eagerly (the default behaviour).

Image Optimisation for LCP

When the LCP element is an image, format and delivery optimisation are critical:

  • Modern formats: Serve WebP or AVIF with fallbacks. AVIF provides 30-50% smaller file sizes than WebP for photographic content, though encoding is slower and browser support is still expanding.
  • Responsive images: Use srcset and sizes attributes to serve appropriately sized images for each viewport. Serving a 2400px image to a 375px mobile screen wastes bandwidth and delays LCP.
  • CDN image transformation: Services like Cloudflare Images, Imgix, or Cloudinary can serve optimised, resized images on the fly based on the requesting device.

Render-Blocking Resources

CSS and synchronous JavaScript block rendering. Until all render-blocking resources are downloaded and parsed, nothing displays — including the LCP element. Advanced mitigation:

  • Inline critical CSS: Extract the CSS required to render above-the-fold content and inline it in the HTML head. Load the full stylesheet asynchronously.
  • Defer non-critical JavaScript: Add the defer attribute to script tags that are not needed for initial render. Use async for scripts that can execute in any order.
  • Reduce CSS file size: Remove unused CSS rules using PurgeCSS or similar tools. Large CSS frameworks (Bootstrap, Tailwind) often include thousands of unused rules that delay parsing.

Font Loading and LCP

Custom web fonts can delay text rendering — and if a text element is your LCP, slow font loading directly increases LCP. Use font-display: swap in your @font-face declarations to show text immediately in a system font and swap to the custom font once loaded. Preload critical fonts as shown above. Consider using system font stacks for body text where brand requirements permit, eliminating font loading delay entirely.

INP Deep Dive: Measuring and Reducing Input Delay

Interaction to Next Paint measures the time from a user interaction (click, tap, keypress) to when the browser paints the next frame reflecting that interaction. Unlike FID, which only measured the delay before the first interaction’s event handler ran, INP measures every interaction throughout the page lifecycle and reports the worst (or near-worst) value.

Why INP Is Harder Than FID

FID was relatively easy to pass because it only measured input delay — the time the main thread was blocked when the user first interacted. Most sites loaded their heaviest JavaScript before users interacted, so FID was often excellent. INP measures the complete interaction lifecycle for every interaction: input delay (time waiting for the main thread), processing time (event handler execution), and presentation delay (time to render the visual update).

A site may have excellent INP on page load but terrible INP when a user clicks a filter button that triggers expensive DOM manipulation. INP captures these mid-session interactions that FID missed entirely.

Measuring INP

INP is only available as a field metric — it cannot be fully replicated in lab conditions because it depends on real user interaction patterns. Use the Chrome User Experience Report (CrUX) for aggregate field data, the Web Vitals JavaScript library for per-user measurement, and Chrome DevTools’ Performance panel for debugging specific interactions.

The Web Vitals library can log every interaction with its INP contribution:

import {onINP} from 'web-vitals';

onINP(({value, entries}) => {
  entries.forEach(entry => {
    console.log('INP interaction:', {
      value: entry.duration,
      target: entry.target,
      name: entry.name,
      inputDelay: entry.processingStart - entry.startTime,
      processingTime: entry.processingEnd - entry.processingStart,
      presentationDelay: entry.startTime + entry.duration - entry.processingEnd
    });
  });
});

Reducing Input Delay

Input delay occurs when the main thread is busy and cannot immediately respond to a user interaction. The primary cause is long-running JavaScript tasks. Solutions include:

  • Break up long tasks: JavaScript tasks exceeding 50ms block the main thread. Use scheduler.yield() (where supported) or setTimeout to break long operations into smaller chunks that yield to the main thread between iterations.
  • Reduce third-party script impact: Analytics, advertising, and chat widgets often run periodic tasks that block the main thread. Audit third-party scripts and load them with async/defer, or use a tag manager with delayed loading.
  • Web Workers for computation: Move data processing, sorting, filtering, and other computationally intensive work to Web Workers, keeping the main thread free for user interactions.

Reducing Processing Time

Event handler processing time depends on the complexity of the JavaScript executed in response to the interaction. Common causes of slow processing:

  • Expensive DOM manipulation: Reading and writing to the DOM alternately forces layout recalculation (layout thrashing). Batch DOM reads, then batch DOM writes.
  • State management overhead: In React/Vue applications, state updates can trigger unnecessary re-renders of large component trees. Use memoisation (React.memo, useMemo, computed properties in Vue) to prevent cascading re-renders.
  • Synchronous API calls: Event handlers that make synchronous network requests block until the response arrives. Always use asynchronous patterns for network operations within event handlers.

Reducing Presentation Delay

Presentation delay is the time between event handler completion and the browser painting the updated frame. This is primarily driven by rendering complexity — the browser must recalculate styles, perform layout, and paint. Reduce presentation delay by:

  • Minimising layout recalculations: Use CSS transforms and opacity for animations rather than properties that trigger layout (width, height, top, left).
  • Reducing DOM size: Pages with thousands of DOM nodes require more time for layout and paint operations. Target under 1,500 DOM nodes for optimal performance.
  • Content-visibility CSS property: Apply content-visibility: auto to off-screen sections, telling the browser to skip rendering them until they enter the viewport.

CLS Elimination Techniques

Cumulative Layout Shift measures unexpected visual movement of page elements during loading. CLS below 0.1 is considered good. Unlike LCP and INP, CLS issues are often caused by missing dimensions, late-loading resources, or dynamic content injection rather than raw performance problems.

Reserve Space for Dynamic Content

The most common CLS cause is content that changes size after initial render. Prevent this by explicitly reserving space:

Images and videos: Always include width and height attributes on img and video elements. Modern browsers use these to calculate aspect ratios before the resource loads, preventing layout shift.

<img src="photo.webp" width="800" height="450" alt="Description">

<!-- Or use CSS aspect-ratio -->
<style>
.hero-image {
  aspect-ratio: 16 / 9;
  width: 100%;
  height: auto;
}
</style>

Advertisements and embeds: Ad slots are notorious CLS offenders because ad content arrives asynchronously with unpredictable dimensions. Reserve minimum height for ad containers using CSS min-height. If your ad network provides size information, use it to set exact dimensions.

Web fonts: Font swap can cause layout shift when the custom font renders at a different size than the fallback. Use the CSS size-adjust property to match the fallback font’s metrics to the custom font, eliminating shift during the swap.

@font-face {
  font-family: 'CustomFont';
  src: url('/fonts/custom.woff2') format('woff2');
  font-display: swap;
  size-adjust: 105%;
  ascent-override: 90%;
  descent-override: 20%;
  line-gap-override: 0%;
}

Avoid Injecting Content Above Existing Content

Dynamically inserting banners, notification bars, or cookie consent notices above existing content pushes everything down, causing layout shift. Instead, reserve space in the initial HTML for these elements, or insert them in a way that does not shift existing content — for example, overlaying content with fixed or sticky positioning rather than pushing it down.

Animation-Related CLS

CSS animations and transitions can trigger CLS if they affect layout properties. Animations that change height, width, padding, margin, or position (other than transform) cause layout shifts. Use transform: translateY() instead of changing top or margin-top. Use transform: scale() instead of changing width/height.

Late-Loading Third-Party Widgets

Social media embeds, map widgets, and review carousels often load asynchronously and inject content with unpredictable dimensions. Where possible, use static placeholders with defined dimensions and load the interactive widget on user interaction (click to load). This eliminates CLS from third-party widgets whilst also improving page load performance.

CLS in Single-Page Applications

SPAs experience CLS not just on initial load but during client-side navigation. When navigating between “pages” within an SPA, the transition period — when old content is removed and new content is rendered — can generate significant CLS. Implement skeleton screens or maintain previous content until new content is fully ready, using a fade transition rather than incremental content injection. Your web development team should test CLS across all navigation paths, not just initial page loads.

Performance Budgets and Monitoring

Achieving good Core Web Vitals is only valuable if you maintain them. Performance budgets and continuous monitoring prevent regression.

Setting Performance Budgets

A performance budget defines maximum acceptable values for performance metrics. For Core Web Vitals, your budgets should be stricter than Google’s thresholds to provide a safety margin:

  • LCP budget: Under 2.0 seconds (Google threshold: 2.5s)
  • INP budget: Under 150 milliseconds (Google threshold: 200ms)
  • CLS budget: Under 0.05 (Google threshold: 0.1)
  • Total JavaScript size: Under 300KB compressed
  • Total page weight: Under 1.5MB for initial load
  • Third-party script count: Maximum 5 unique third-party origins

Enforce budgets in your build pipeline. Tools like bundlesize, Lighthouse CI, and webpack-bundle-analyzer can fail builds that exceed budget thresholds, preventing performance regressions from reaching production.

Real User Monitoring (RUM)

Lab tests (Lighthouse, WebPageTest) provide controlled measurements but do not capture real user experience diversity. Implement Real User Monitoring to collect CWV data from actual visitors across all devices, connection speeds, and geographic locations.

For Singapore audiences, RUM data often reveals that mobile performance on 4G connections is significantly worse than lab tests on fast WiFi suggest. The 75th percentile — the value that determines your CrUX score — is dragged down by users on slower connections and older devices. RUM data identifies which user segments experience poor performance.

Automated Regression Detection

Integrate performance testing into your CI/CD pipeline. Every deployment should trigger Lighthouse CI or a similar tool that compares current performance against baselines and budgets. Configure alerts for: any CWV metric crossing the “good” threshold, any metric degrading by more than 10% from the previous deployment, and JavaScript bundle size increasing beyond budget.

Competitor Benchmarking

CrUX data is publicly available for any site with sufficient traffic. Use the CrUX API or tools like Treo, PageSpeed Compare, or the CrUX Dashboard to benchmark your CWV scores against competitors. If competitors pass all CWV thresholds and you do not, you have a quantifiable competitive disadvantage in Google’s rankings. A comprehensive digital marketing strategy includes performance benchmarking as a standard practice.

Infrastructure-Level Optimisations

Some of the most impactful CWV improvements come from infrastructure changes rather than code-level fixes.

CDN Configuration

A properly configured CDN can cut LCP by hundreds of milliseconds by serving content from edge nodes close to your users. For Singapore-focused sites, ensure your CDN has points of presence in Singapore or nearby regions (Hong Kong, Tokyo). Key CDN configurations for CWV:

  • Cache HTML pages: For sites with infrequent content changes, cache full HTML pages at the CDN edge. This reduces TTFB to under 50ms for cached pages.
  • Image CDN: Use a CDN that automatically serves optimised, properly sized images in modern formats based on the requesting device.
  • HTTP/3 support: HTTP/3 (QUIC) reduces connection establishment time, particularly beneficial for mobile users on unstable connections.
  • Early Hints (103): Configure your CDN to send 103 Early Hints responses, allowing the browser to begin preloading critical resources before the full HTML response arrives.

Server-Side Rendering Infrastructure

For JavaScript-heavy sites, SSR infrastructure directly affects LCP. The SSR server must render pages quickly — a slow SSR server negates the SEO benefits of server rendering. Use caching (ISR, stale-while-revalidate patterns) to avoid re-rendering unchanged pages on every request. Scale SSR servers horizontally to handle traffic spikes without TTFB degradation.

Hosting and Compute

Shared hosting environments, where your site shares CPU and memory with other tenants, produce inconsistent TTFB. For performance-critical sites, dedicated or container-based hosting (AWS ECS, Google Cloud Run, DigitalOcean App Platform) provides predictable resources. Edge compute platforms (Cloudflare Workers, Vercel Edge Functions, Deno Deploy) eliminate server-to-CDN latency by running application code at the CDN edge.

Database Performance

For dynamic sites, database query time is often the largest component of TTFB. Advanced database optimisations include: read replicas in the same region as your application server, query result caching with appropriate invalidation, connection pooling to eliminate connection establishment overhead, and database-level query analysis to identify and optimise slow queries.

Framework-Specific Performance Fixes

Each frontend framework has specific performance characteristics and optimisation techniques.

WordPress

WordPress sites commonly fail CWV due to plugin bloat and render-blocking resources. Advanced WordPress CWV fixes include:

  • Remove unused plugins: Each plugin adds JavaScript and CSS. Audit every plugin and remove those not actively needed.
  • Implement object caching: Redis or Memcached for WordPress object caching can reduce TTFB by 60-80% on database-heavy pages.
  • Use a performance-oriented theme: Themes like GeneratePress, Kadence, or custom lightweight themes produce significantly less HTML, CSS, and JavaScript than page-builder-dependent themes.
  • Defer WooCommerce scripts: WooCommerce loads cart and checkout JavaScript on every page. Defer or conditionally load these scripts only on pages where they are needed.

React and Next.js

React’s virtual DOM and reconciliation process can cause INP issues when component trees are large. Optimisations include:

  • React.memo and useMemo: Prevent unnecessary re-renders of expensive components.
  • Code splitting: Use dynamic imports (React.lazy, next/dynamic) to split JavaScript into page-specific bundles rather than loading the entire application on every page.
  • Server Components (Next.js App Router): React Server Components render on the server and send only HTML to the client — no hydration JavaScript required. Use Server Components for static content and reserve Client Components for interactive elements.
  • Streaming SSR: Next.js App Router streams HTML to the browser as components render, reducing TTFB and enabling progressive rendering.

Shopify

Shopify sites are constrained by the platform’s shared infrastructure but can still achieve good CWV. Focus on theme performance (Dawn, the default theme, is well-optimised), minimise app scripts (each Shopify app injects its own JavaScript), use Shopify’s native lazy loading, and optimise Liquid template rendering to reduce server-side processing time.

Static Site Generators

Sites built with Astro, Hugo, Eleventy, or similar tools inherently perform well on CWV because they produce minimal JavaScript and static HTML. The primary CWV concern is image optimisation and third-party script management. Use the framework’s built-in image optimisation (Astro’s Image component, Hugo’s image processing) and defer all third-party scripts. A well-executed content marketing website built on a static site generator can achieve near-perfect CWV scores with minimal effort.

Frequently Asked Questions

How much do Core Web Vitals actually affect rankings?

Core Web Vitals are a confirmed ranking signal but function as a tiebreaker rather than a dominant factor. Content relevance, backlinks, and search intent alignment remain far more influential. In competitive niches where multiple pages have similar content quality and authority, CWV can be the differentiating factor. Sites failing CWV are at a quantifiable disadvantage but will not drop dramatically solely due to poor performance.

What is the difference between lab data and field data for CWV?

Lab data comes from controlled tests (Lighthouse, WebPageTest) run on a specific device and connection speed. Field data comes from real users via the Chrome User Experience Report (CrUX). Google uses field data for ranking purposes — lab data is a diagnostic tool. A site may score perfectly in lab tests but fail in field data if real users experience the site on slower devices or connections than the lab simulates.

Why does my site pass Lighthouse but fail CrUX for Core Web Vitals?

Lighthouse tests simulate a single device and connection (typically a mid-tier mobile device on a fast 4G connection). CrUX reports the 75th percentile of all real user experiences, including users on older phones, slower connections, and with different interaction patterns. The 25% of users with the worst experience drag down your CrUX scores. Optimise for real-world diversity, not just lab conditions.

How do I fix INP issues caused by third-party scripts?

Third-party scripts (analytics, ads, chat widgets) are a leading cause of poor INP because they run periodic tasks on the main thread. Solutions include: loading third-party scripts with async or defer attributes, using a tag manager with delayed loading (load after user interaction), implementing third-party scripts in Web Workers where possible (using Partytown or similar libraries), and auditing whether each third-party script is genuinely necessary.

Does CLS measurement include user-initiated layout shifts?

No. CLS only measures unexpected layout shifts — shifts that occur without user interaction within the preceding 500ms. If a user clicks a button and content expands, that shift is expected and excluded from CLS. However, if a user clicks a button and unrelated content elsewhere on the page shifts (e.g., an ad loads), that unrelated shift does count towards CLS.

How can I improve LCP for pages with large hero images?

Preload the hero image with rel=”preload” and fetchpriority=”high”. Serve the image in WebP or AVIF format at the exact dimensions needed (not larger). Use responsive images with srcset to serve appropriate sizes per viewport. Ensure no render-blocking CSS or JavaScript delays the image render. Consider using a CSS background with a low-quality image placeholder that displays instantly whilst the full image loads.

What is a good INP score to aim for?

Google’s threshold for “good” INP is under 200 milliseconds. Aim for under 150ms to provide a buffer. Elite performance is under 100ms, where interactions feel instantaneous. Monitor your 75th percentile INP in CrUX data — this is the value that determines your page experience signal. Individual interactions above 200ms are acceptable as long as they do not represent more than 25% of all interactions.

How do ads and iframes affect Core Web Vitals?

Ads and iframes commonly cause CLS (injecting content that shifts layout), increase LCP (by competing for bandwidth during page load), and worsen INP (by running JavaScript that blocks the main thread). Mitigate by reserving explicit dimensions for all ad containers, loading ads asynchronously after critical content, and using lazy loading for below-the-fold ad slots and iframes.

Should I prioritise LCP, INP, or CLS optimisation first?

Prioritise the metric that currently fails the “good” threshold. If multiple metrics fail, start with LCP because it affects the broadest range of users (everyone waits for the page to load), then CLS (layout shifts frustrate all users), then INP (interaction delays affect engaged users). If all three are in the “good” range, focus on maintaining them through performance budgets and monitoring.

How long does it take for CWV improvements to affect rankings?

Google’s CrUX data is collected over a rolling 28-day period. After deploying CWV improvements, it takes approximately 28 days for the improvements to fully reflect in CrUX data. Google then needs to process and incorporate this updated data into its ranking systems. In practice, expect four to eight weeks between deploying improvements and observing any ranking impact. Monitor CrUX data in Search Console’s Core Web Vitals report to track progress.