Core Web Vitals (CWVs) measure user experience using three key metrics: Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS).
Optimizing Core Web Vitals is essential because these metrics directly affect user experience and search rankings.
In brief:
- Improve server response, image delivery, and JavaScript execution to boost performance.
- Strapi v5’s headless architecture supports Core Web Vitals optimization via decoupled content delivery.
- Continuous monitoring with the right tools is used to maintain and improve site performance.
Let's dive into how to improve core web vitals.
What Are Core Web Vitals?
Core Web Vitals are three performance metrics defined by Google that measure key aspects of user experience on a webpage, specifically loading speed, interactivity, and visual stability. These metrics are part of Google’s page experience signals and can directly impact your site’s SEO rankings.
The three CWVs are:
- Largest Contentful Paint (LCP): Measures how quickly the main content of a page becomes visible, typically the largest image or text block in the viewport.
- Interaction to Next Paint (INP): Measures how long it takes for the interface to respond after a user interaction, like clicking a button or tapping a menu.
- Cumulative Layout Shift (CLS): Measures how much the layout shifts unexpectedly while the page is loading, like buttons jumping or text moving as images load.
Note: Google replaced First Input Delay (FID) with INP in March 2024 for a more accurate reflection of real-world interactivity.
How to Improve Largest Contentful Paint (LCP)
LCP measures how quickly the largest visible element loads on your page. This element is a hero image or a large text block.
How quickly your page loads directly affects the first impression users (and search engines) get. Aim for an LCP of under 2.5 seconds for optimal performance.
Here are four high-impact ways to improve LCP:
Optimize Server Response Times
Optimizing server response times helps the browser load and render key visual elements faster, which directly improves LCP.
To reduce delays in delivering your largest contentful element, focus on the following server-side optimizations:
. To improve this:
- Use fast, reliable hosting optimized for dynamic content (e.g., VPS, Strapi Cloud, or dedicated infrastructure).
- Set up a Content Delivery Network (CDN) to serve content from locations closer to your users. For example, you can configure the Strapi API with a CDN to optimize content delivery.
- Reduce time to render the LCP element by minimizing backend logic that delays content generation—optimize Strapi’s API queries and avoid unnecessary plugins or middleware.
- Cache HTML and API responses where possible to avoid recomputing layout-critical content for each request.
Minimize Render-Blocking Resources
Large or poorly loaded JavaScript and CSS files can block the browser from displaying content quickly. Reduce their impact to speed up your LCP by doing the following:
- Add the
defer
attribute to scripts that aren't immediately needed. - Place critical CSS directly in the
<head>
of your HTML. - Load non-critical CSS asynchronously using
preload
:
1<link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'">
Optimize Images
Images are often the largest contentful element on your page. Optimize your images to reduce LCP by doing the following:
- Use WebP and AVIF formats to reduce file size without quality loss.
- Make images responsive with
srcset
andsizes
:
1<img
2 src="image-1x.jpg"
3 srcset="image-1x.jpg 1x, image-2x.jpg 2x, image-3x.jpg 3x"
4 sizes="(max-width: 800px) 100vw, 50vw"
5 alt="Responsive image example"
6/>
- Compress images using tools like TinyPNG.
- Lazy-load offscreen images using
loading="lazy"
to reduce initial page weight.
Prioritize Critical Resources
Make sure the resources for your LCP element load quickly:
- Use
preload
to tell browsers which assets matter most:
1<link rel="preload" as="image" href="hero-image.webp">
- Cut down what you need for the initial render. Remove or defer unnecessary scripts, fonts, or third-party tools that slow down the main content.
How to Improve Interaction to Next Paint (INP)
INP measures how long it takes your site to respond to user interactions like clicks, taps, or keyboard input. A low INP score means a site feels responsive, so aim for an INP under 200ms.
Break Up Long JavaScript Tasks
When JavaScript hogs the main thread, your site feels frozen:
- Use Chrome DevTools to detect tasks that block the main thread.
- Split long tasks into smaller, asynchronous chunks.
- Move heavy calculations to Web Workers where they won't interfere with interactions.
Reduce JavaScript Bundle Size
Large bundles take longer to parse and delay your site’s responsiveness.
Reduce your bundle size by doing the following:
- Split your code into smaller chunks that load when needed.
- Use dynamic imports for features that aren't needed right away.
- Remove dead code with tree shaking.
For React apps using Next.js, try this approach:
1import dynamic from 'next/dynamic'
2
3const DynamicComponent = dynamic(() => import('../components/heavy-component'))
This loads heavy components only when necessary, keeping your initial load light and fast.
Defer or Remove Third-Party Scripts
Third-party scripts often cause the worst performance issues
To reduce their impact on responsiveness, audit and control how and when they load:
- Remove any non-essential third-party scripts.
- Use
async
ordefer
to load non-critical scripts without blocking the main thread. - Host critical scripts yourself to reduce load times and improve control.
Optimize Event Handlers
Poorly managed event listeners can overwhelm the browser during user interactions, especially on input, scroll, or resize events.
Use these techniques to limit how often your event handlers run and avoid unnecessary work on the main thread:
- Use debouncing for input operations:
1function debounce(func, timeout = 300) {
2 let timer;
3 return (...args) => {
4 clearTimeout(timer);
5 timer = setTimeout(() => { func.apply(this, args); }, timeout);
6 };
7}
8
9const processChange = debounce(() => saveInput());
- Apply throttling for scroll or resize events:
1function throttle(func, limit = 300) {
2 let inThrottle;
3 return function() {
4 const args = arguments;
5 const context = this;
6 if (!inThrottle) {
7 func.apply(context, args);
8 inThrottle = true;
9 setTimeout(() => inThrottle = false, limit);
10 }
11 }
12}
13
14window.addEventListener('scroll', throttle(handleScroll));
These techniques prevent your event handlers from overwhelming the browser.
Use Web Workers for Heavy Processing
Web Workers let you move expensive logic off the main thread so it doesn't block user interactions.
The example below shows how to offload complex calculations to a separate thread using a Web Worker:
1// main.js
2const worker = new Worker('worker.js');
3worker.postMessage({data: complexData});
4worker.onmessage = function(e) {
5 console.log('Processed result:', e.data);
6};
7
8// worker.js
9self.onmessage = function(e) {
10 const result = performComplexCalculation(e.data);
11 self.postMessage(result);
12};
This keeps the main thread free to handle user interactions.
How to Improve Cumulative Layout Shift (CLS)
Remember clicking a button just as the page jumps, causing you to hit something else? That's poor CLS at work. A good score is under 0.1. Here's how you can get there.
Set Image Dimensions to Prevent Shifts
When images don’t have defined width and height, they load unpredictably, causing surrounding content to jump.
How to fix it:
- Always specify image dimensions in HTML:
1<img src="example.jpg" width="800" height="600" alt="Example image">
- Use responsive CSS that respects the image’s aspect ratio:
1img {
2 max-width: 100%;
3 height: auto;
4}
Reserve Space for Injected Content
Ads, embeds, and dynamic content often appear after page load and push content around when they do.
Here’s what you can do to prevent that:
- Reserve space for them with placeholders before they load
- Create aspect ratio boxes with CSS:
1.ad-container {
2 position: relative;
3 width: 100%;
4 padding-top: 56.25%; /* 16:9 Aspect Ratio */
5}
6.ad-content {
7 position: absolute;
8 top: 0;
9 left: 0;
10 width: 100%;
11 height: 100%;
12}
Use Font Loading Strategies That Avoid Shifts
Custom web fonts can cause layout shifts when fallback text is swapped after the font finishes loading.
Prevent that by doing the following:
- Use
font-display: swap
in your@font-face
rules:
1@font-face {
2 font-family: 'MyWebFont';
3 src: url('myfont.woff2') format('woff2');
4 font-display: swap;
5}
- Preload critical fonts:
1<link rel="preload" href="myfont.woff2" as="font" type="font/woff2" crossorigin>
Layout-Affecting Animations
Animations that move or resize elements using properties like top
, left
, width
, or height
can trigger layout recalculations, causing visible shifts and hurting your CLS score.
To avoid this, use compositing-friendly properties like transform
and opacity
. These properties don’t force the browser to recalculate layout or repaint large portions of the page—they simply update the element’s appearance on the GPU layer, making them far more performance-friendly.
Here’s an example of an animation that scales and fades an element smoothly without causing layout shifts:
1.animate-element {
2 transition: transform 0.3s ease, opacity 0.3s ease;
3}
4.animate-element:hover {
5 transform: scale(1.1);
6 opacity: 0.8;
7}
By using transform
and opacity
, your animations feel smooth and responsive without disrupting the layout around them.
Debug Layout Shifts Using Chrome DevTools
Use Chrome DevTools to spot exactly what’s shifting and why. Here’s how:
- Use Layout Shift Regions in the Performance tab to visualize layout changes.
- Enable the "Core Web Vitals" overlay to see CLS scores in real time.
Focus on proper image handling, reserved space for dynamic content, optimized font loading, and stable animations. Your users will thank you for not making them play "whack-a-mole" with your interface.
Tools to Measure Core Web Vitals
The tools below help you track CWVs using both real-world performance data and controlled lab environments, giving you a complete picture of how your site performs.
Field Data Tools
These tools measure Core Web Vitals based on how actual users experience your site in real-world conditions—across devices, network speeds, and locations.
- Chrome User Experience Report (CrUX) and CrUX Vis: Visualize long-term Core Web Vitals performance with trend data, device filtering, and experience breakdowns.
- Google Search Console’s Core Web Vitals Report: Identifies pages with similar performance issues and groups them for easier prioritization and debugging.
- Sematext Experience: Provides real-time performance data from actual users to give a broader view of overall page speed and responsiveness.
Note: Sematext is one of several Real User Monitoring (RUM) tools. Others include Google Analytics with Web Vitals integration, SpeedCurve, and New Relic.
Lab Data Tools
These tools simulate user experience in a controlled environment, which is ideal for debugging and validating performance changes.
- Google PageSpeed Insights: Combines field and lab data, offering specific recommendations for improving each Core Web Vital.
- Lighthouse in Chrome DevTools: Provides deep audits for performance, SEO, accessibility, and CWVs. This tool is built into your browser.
- WebPageTest: Lets you run tests from different global locations and network conditions for a complete performance snapshop.
How to Improve Core Web Vitals Optimization with Strapi
Strapi v5 is built with modern performance in mind, giving developers fine-grained control over how content loads, how assets are delivered, and how the frontend responds.
As Google’s Core Web Vitals become more central to SEO and UX, Strapi offers a fast, flexible foundation for building optimized web experiences.
Here’s how Strapi v5 supports better performance across LCP, INP, and CLS:
Faster load times through a decoupled architecture. Content delivery is separated from the backend CMS, which allows you to optimize APIs and page rendering independently. Strapi v5 further improves performance with faster API response times, outlined in the official documentation.
Full control over asset delivery. You can serve responsive images, lazy-load offscreen content, adopt modern formats like WebP, and implement smart caching strategies—all of which help reduce load times and visual instability.
Seamless integration with frameworks like Next.js. Strapi works with SSG, SSR, and ISR to optimize how pages are rendered and updated. You can fine-tune data transfer and rendering strategy based on your content needs. Learn more in this guide to Next.js performance optimization.
Developer-focused performance tooling. Strapi v5 gives you precise control over caching, CDN integration, bundle optimization, and custom API endpoints. The improved TypeScript support and more efficient data handling make it even easier to build for speed.
Proven in real-world setups. For example, one team used Strapi v5 with Next.js SSG, ISR, and the built-in Image component to reduce LCP by 40% and bring CLS below 0.1. You can manage content in Strapi, optimize delivery with Next.js, and deliver fast, stable experiences with minimal overhead.
Strapi v5 gives you the tools to stay fast as your site grows. To dive deeper, explore the full Strapi 5 documentation.