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:
Let's dive into how to improve 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:
Note: Google replaced First Input Delay (FID) with INP in March 2024 for a more accurate reflection of real-world interactivity.
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:
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:
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:
defer
attribute to scripts that aren't immediately needed. <head>
of your HTML. preload
:1<link rel="preload" href="non-critical.css" as="style" onload="this.rel='stylesheet'">
Images are often the largest contentful element on your page. Optimize your images to reduce LCP by doing the following:
srcset
and sizes
: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/>
loading="lazy"
to reduce initial page weight.Make sure the resources for your LCP element load quickly:
preload
to tell browsers which assets matter most:1<link rel="preload" as="image" href="hero-image.webp">
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.
When JavaScript hogs the main thread, your site feels frozen:
Large bundles take longer to parse and delay your site’s responsiveness.
Reduce your bundle size by doing the following:
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.
Third-party scripts often cause the worst performance issues
To reduce their impact on responsiveness, audit and control how and when they load:
async
or defer
to load non-critical scripts without blocking the main thread. 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:
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());
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.
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.
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.
When images don’t have defined width and height, they load unpredictably, causing surrounding content to jump.
How to fix it:
1<img src="example.jpg" width="800" height="600" alt="Example image">
1img {
2 max-width: 100%;
3 height: auto;
4}
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:
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}
Custom web fonts can cause layout shifts when fallback text is swapped after the font finishes loading.
Prevent that by doing the following:
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}
1<link rel="preload" href="myfont.woff2" as="font" type="font/woff2" crossorigin>
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.
Use Chrome DevTools to spot exactly what’s shifting and why. Here’s how:
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.
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.
These tools measure Core Web Vitals based on how actual users experience your site in real-world conditions—across devices, network speeds, and locations.
Note: Sematext is one of several Real User Monitoring (RUM) tools. Others include Google Analytics with Web Vitals integration, SpeedCurve, and New Relic.
These tools simulate user experience in a controlled environment, which is ideal for debugging and validating performance changes.
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.