Back to blog

How to Get a 100/100 Lighthouse Score: Core Web Vitals Optimization Guide

A fast website is no longer just a luxury. It is a critical requirement for user engagement and search engine optimization (SEO). Google uses Core Web Vitals as official ranking factors, meaning page speed directly impacts search traffic.

Lighthouse is the standard tool for measuring web performance. Achieving a perfect 100/100 score requires a deep understanding of browser rendering pipelines and asset optimization.

In this guide, we will break down the core metrics (LCP, INP, CLS) and explore practical strategies to optimize your frontend codebase for a perfect Lighthouse score.

Understanding Core Web Vitals

To optimize performance, you must understand what Lighthouse is measuring:

  • Largest Contentful Paint (LCP): Measures loading performance. It marks the time when the main content of a page (usually the hero image or headline text) has likely loaded. Target: Under 2.5 seconds.
  • Interaction to Next Paint (INP): Measures page responsiveness. It quantifies how quickly a page responds to user actions (like clicks or key presses) throughout the entire visit. Target: Under 200 milliseconds.
  • Cumulative Layout Shift (CLS): Measures visual stability. It tracks unexpected layout shifts that occur while elements are loading. Target: Less than 0.1.

Optimizing Largest Contentful Paint (LCP)

LCP is typically bottlenecked by heavy images or render-blocking scripts that delay the browser from painting the page.

1. Preload the Hero Image

If your page contains a large banner or hero image, the browser must discover and load it as early as possible. Do not wait for the stylesheet to load before starting the download. Use HTML preloading:

<link
  rel="preload"
  as="image"
  href="/hero-image.webp"
  fetchpriority="high"
/>

Setting fetchpriority to high instructs the browser to download this asset before other non-critical page resources.

2. Compress and Use Modern Formats

Never serve raw JPEG or PNG files. Convert your images to modern web formats like WebP or AVIF, which offer up to 50 percent better compression at identical qualities. Additionally, utilize responsive picture elements to serve smaller image dimensions to mobile screens:

<picture>
  <source srcset="/hero-mobile.webp" media="(max-width: 600px)" />
  <img src="/hero-desktop.webp" alt="Hero banner" width="1200" height="600" />
</picture>

3. Eliminate Render-Blocking Resources

By default, standard scripts and stylesheets block the browser from painting HTML elements.

  • For CSS: Inline critical CSS directly inside the <head> of the document to style the above-the-fold content immediately. Load non-critical stylesheets asynchronously.
  • For JS: Apply defer or async attributes to all scripts to prevent them from blocking HTML parser loops.
<script src="/app.js" defer></script>

Optimizing Interaction to Next Paint (INP)

INP measures how long the main thread is blocked when users try to interact with the page. Long-running JavaScript tasks are the primary cause of high INP values.

  • Break Up Long Tasks: Any JavaScript execution taking longer than 50ms is flagged as a Long Task. Break complex calculations into smaller chunks using setTimeout or requestIdleCallback.
  • Utilize Web Workers: Move CPU-intensive calculations (such as parsing data schemas or rendering complex graphics) off the main thread entirely by using Web Workers.
  • Defer Non-Critical JS: Do not load analytics trackers or chat widgets until the main page lifecycle is complete.

Mitigating Cumulative Layout Shift (CLS)

CLS issues occur when elements (such as images, ad banners, or late-loading fonts) dynamically pop onto the screen, pushing other elements down.

1. Always Declare Media Dimensions

When loading images, videos, or iframe ads, always specify width and height attributes or configure CSS aspect-ratio properties. This allows the browser to reserve the exact layout box space before the asset finishes downloading.

.banner-image {
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
}

2. Optimize Custom Web Fonts

Custom web fonts can trigger a layout shift when the font finishes downloading and swaps with the system fallback font.

  • Use font-display: swap in your @font-face rules to ensure text renders immediately using the fallback font.
  • Preload critical font files in HTML.
  • Match the metrics of your fallback font (using line-height, letter-spacing adjustments) to the web font to prevent layout shifting during the swap.
@font-face {
  font-family: "CustomFont";
  src: url("/fonts/custom.woff2") format("woff2");
  font-display: swap;
}

Conclusion

Getting a 100/100 Lighthouse score is not about a single performance hack; it requires a systematic approach to asset loading and browser rendering. By preloading LCP resources, deferring render-blocking scripts, breaking up long JavaScript execution loops to protect INP, and explicitly sizing images and custom web fonts to prevent CLS, you can deliver an optimized user experience and maximize your search engine rankings.