Core Web Vitals have become a crucial Google ranking factor. As we explain in our article on why fast sites rank better, these metrics measure the real user experience of your site. In this technical guide, we detail practical optimizations to improve each of the three metrics: LCP, INP, and CLS.
Recap: The Three Core Web Vitals
Before diving into optimizations, let's quickly recap the thresholds to achieve:
- LCP (Largest Contentful Paint) : less than 2.5 seconds — measures perceived load speed.
- INP (Interaction to Next Paint) : less than 200 milliseconds — measures interaction responsiveness.
- CLS (Cumulative Layout Shift) : less than 0.1 — measures visual stability of the page.
Improving LCP (Largest Contentful Paint)
LCP is often the most problematic metric. It depends on several factors: server response time, loading of critical resources, and client-side rendering.
1. Optimize Images
The LCP element is often a hero image or banner. Here are the essential optimizations:
- Modern format: use WebP or AVIF instead of JPEG/PNG. The weight savings are 25 to 50% without visible quality loss. For WordPress sites, our H1Site WebP Converter plugin automates this conversion.
- Proper sizing: don't serve a 4000 px wide image if it displays at 800 px. Use the
srcsetattribute and thesizesattribute to serve the right size according to the viewport. - Preload the LCP image: add
<link rel="preload" as="image" href="...">in the <code><head></code> for the LCP image. This tells the browser to start downloading it immediately, without waiting for CSS or JavaScript to discover it. - Do not lazy-load the LCP image: lazy loading is great for below-the-fold images, but the LCP image must load immediately. Add
loading="eager"andfetchpriority="high". - Use an image CDN: services like Cloudinary, imgix, or Vercel's CDN optimize and serve images from servers close to the user.
2. Optimize Fonts
Web fonts can block text rendering and delay LCP.
- font-display: swap: this CSS property immediately displays text with a fallback system font, then switches to the web font when loaded. Text is visible from the start, improving LCP.
- Preload critical fonts: add
<link rel="preload" as="font" type="font/woff2" crossorigin href="...">for fonts used above the fold. - Host fonts locally: instead of using Google Fonts via their CDN (which adds an extra DNS connection), download font files and serve them from your domain.
- Limit the number of fonts: each additional font (and each weight variant) adds kilobytes. Limit yourself to 2 fonts and 3 to 4 weight variants maximum.
3. Reduce Server Response Time (TTFB)
Time to First Byte is the foundation of LCP. If your server takes 2 seconds to respond, your LCP cannot be below 2 seconds.
- Choose a performant hosting: a shared hosting at $5/month cannot compete with optimized hosting. As we explain in our article on reasons for a slow site, cheap hosting is the primary cause of slowness.
- Enable server caching: for WordPress, use a caching plugin (WP Rocket, LiteSpeed Cache). For Next.js, SSG and ISR ensure minimal TTFB thanks to the CDN.
- Use a CDN: a Content Delivery Network serves pages from a server geographically close to the user. Cloudflare (free) or Vercel Edge Network significantly reduce TTFB.
- Optimize database queries: for WordPress, add indexes, clean up unnecessary tables (revisions, transients), and use an object cache (Redis, Memcached).
4. Eliminate Render-Blocking Resources
- Inline critical CSS: embed the necessary CSS for above-the-fold content directly in HTML. Defer loading the rest of the CSS.
- Defer/async JavaScript: add
deferorasyncto script tags that are not critical for initial rendering. - Reduce critical request chains: minimize the number of resources that must load sequentially before content is displayed.
Improving INP (Interaction to Next Paint)
INP measures the time between a user interaction (click, tap, key press) and the resulting visual update. A high INP means your site feels unresponsive.
1. Reduce Main JavaScript
- Code splitting: split your JavaScript into chunks loaded on demand. With Next.js, code splitting is automatic per page. With webpack, use
import()dynamically. - Tree shaking: eliminate unused JavaScript code. Modern bundlers (webpack, esbuild, SWC) do this automatically if you use ES module imports.
- Audit dependencies: check the size of each npm package with tools like bundlephobia.com. Replace heavy libraries with lighter alternatives (e.g., day.js instead of moment.js).
- Minify and compress: minify your JavaScript (Terser, SWC) and serve it compressed in Brotli or Gzip.
2. Optimize Event Handlers
- Avoid long tasks: a 'long task' is a JavaScript task that lasts more than 50 ms and blocks the main thread. Break down heavy processing into smaller chunks with
requestAnimationFrame,requestIdleCallbackorscheduler.yield(). - Debounce and throttle: for frequent events (scroll, resize, input), use debounce or throttle to limit the number of executions.
- Move work off the main thread: use Web Workers for intensive calculations. The main thread remains free to respond to interactions.
- Avoid forced reflows: reading layout followed by writing (e.g., reading
offsetHeightthen modifying the style) forces the browser to recalculate the layout synchronously.
3. Reduce Third-Party Script Impact
- Load third-party scripts deferentially: Google Analytics, chatbots, ad pixels — load them after the main content with
deferor via dynamic loading after interaction. - Use a lightweight consent manager: poorly implemented cookie banners can block the main thread for hundreds of milliseconds.
- Limit the number of third-party scripts: each third-party script adds weight and JavaScript work. Regularly audit and remove those no longer used.
Improving CLS (Cumulative Layout Shift)
CLS measures unexpected visual shifts. A good CLS gives the impression of a stable and professional page.
1. Define Image and Video Dimensions
- Width and height attributes: always add
widthandheightattributes to your<img>and<video>tags. This allows the browser to reserve space before loading. - CSS aspect-ratio: use the CSS property
aspect-ratiofor responsive image and video containers. Example:aspect-ratio: 16/9. - Next.js Image component: the
<Image>component in Next.js automatically handles dimensions and placeholders, eliminating image-related CLS.
2. Manage Web Fonts Without Shift
- font-display: optional: if the web font doesn't load fast enough, the browser keeps the system font. Zero shift, but the custom font may not display on first visits.
- Fonts with similar metrics: choose fallback fonts with metrics (character width, line height) similar to your web font. Next.js does this automatically with the
next/fontmodule. - Preload fonts: preloading critical fonts reduces swap delay and minimizes shift.
3. Reserve Space for Dynamic Content
- Ads and iframes: set a fixed size for ad containers. If an ad doesn't load, the space remains reserved. Use
min-heightto prevent collapses. - Dynamically loaded content: if you inject content via JavaScript (carousels, notifications, cookie bars), reserve space in the CSS layout before loading.
- Avoid above-the-fold insertions: never insert dynamic content above visible content. Notifications and banners should appear in overlay or be pre-reserved in the layout.
4. Animations and Transitions
- Use transform instead of top/left: CSS animations based on
transformandopacitydo not trigger layout recalculation. Animations based ontop,left,width,heightcause CLS. - CSS contain: the
contain: layoutproperty isolates an element from the rest of the layout. Changes inside this element do not affect the rest of the page.
Measurement and Diagnostic Tools
Field Data
Field data reflects real user experience. These are the data Google uses for ranking.
- Google Search Console: Page Experience report — shows URLs that fail or pass Core Web Vitals.
- PageSpeed Insights: the 'Field Data' section displays CrUX metrics for your URL.
- CrUX Dashboard: a Google Data Studio dashboard based on CrUX data — allows tracking over time.
- web-vitals.js: Google's JavaScript library to measure Core Web Vitals in real-time on your site and send data to your analytics tool.
Lab Data
Lab data is useful for diagnosing and testing optimizations in a controlled environment.
- Lighthouse: complete audit in Chrome DevTools. Simulates a mobile device with a slow connection.
- WebPageTest: detailed test with waterfall chart and filmstrip. Allows testing from different locations.
- Chrome DevTools Performance: real-time loading recording. Identifies long tasks, forced reflows, and layout shifts.
Platform-Specific Optimizations
WordPress
WordPress requires specific plugins and configurations for good Core Web Vitals.
- Caching: WP Rocket or LiteSpeed Cache for page cache, browser cache, and minification.
- Images: our H1Site WebP Converter plugin for automatic WebP conversion. Smush or ShortPixel for compression.
- JavaScript: WP Rocket offers JavaScript delay and remove unused CSS. Perfmatters is a lightweight alternative.
- Hosting: Kinsta, Cloudways, or WP Engine for acceptable TTFB. Avoid shared hosting.
- Theme: use a lightweight theme (GeneratePress, Astra, Kadence). Avoid overloaded multipurpose themes.
- Plugins: limit to 15-20 plugins maximum. Each plugin adds CSS, JavaScript, and SQL queries.
Next.js
Next.js offers excellent Core Web Vitals by default, but a few additional optimizations can make a difference.
- Images: use the
<Image>component for automatic optimization. Addpriorityon the LCP image. - Fonts: use
next/fontfor automatic local hosting and elimination of font swap CLS. - SSG/ISR: favor static generation for content pages. ISR allows updates without a full rebuild.
- Server Components: React Server Components reduce JavaScript sent to the client. Keep interactive components (
"use client") to a minimum. - Third-party Scripts: use the
<Script>component in Next.js withstrategy="lazyOnload"to defer loading of non-critical scripts. - Bundle analyzer: use
@next/bundle-analyzerto identify heavy packages and optimize them.
Shopify
Shopify limits server-side optimizations, but several levers remain accessible.
- Theme: use a lightweight theme like Dawn (default Shopify 2.0 theme). Avoid overloaded third-party themes.
- Apps: each Shopify app injects JavaScript. Limit installed apps and regularly audit their impact.
- Images: Shopify automatically optimizes images via its CDN (WebP format, resizing). But ensure you upload reasonably sized images.
- Liquid: optimize Liquid code to reduce unnecessary loops and API requests in templates.
- Lazy loading: apply native lazy loading on below-the-fold images and videos. Avoid it on hero images.
- Preloading: use
<link rel="preload">tags intheme.liquidfor critical resources.
Action Plan: Where to Start?
If you're unsure where to start, here's an action plan by priority:
- Measure first: run a PageSpeed Insights audit and note your current LCP, INP, and CLS scores. Identify the most problematic metric.
- LCP first: it's the metric that fails most often. Start by optimizing the LCP image and TTFB.
- CLS next: add dimensions to images and videos, fix font swap, and reserve space for dynamic content.
- INP last: audit JavaScript, reduce long tasks, and defer third-party scripts.
- Measure again: after each series of optimizations, retest and compare. Field data takes 28 days to update in CrUX.
Conclusion
Improving Core Web Vitals is not a one-time project — it's an ongoing practice. The optimizations described in this article can transform a site with a PageSpeed score of 30 into a 90+ site. The impact on your SEO, conversion rate, and user experience is measurable and significant.
If you need help diagnosing and optimizing your site's performance, our team at H1Site can conduct a full audit and implement optimizations. Whether your site is on WordPress, Next.js, Shopify, or another platform, contact us for a free evaluation.
H1Site
Vaudreuil Web Agency