sodcalculator

10 Tech How-To

How to Measure & Fix JavaScript Web Vitals

Guide 10-11576 · Updated · Step by step

This guide shows you how to measure Core Web Vitals (LCP, INP, CLS) on your site and fix the most common JavaScript-related causes. You’ll learn to use Chrome DevTools and PageSpeed Insights, then apply targeted fixes for slow loading, input lag, and layout shifts. No prior performance experience is needed, but basic familiarity with browser DevTools helps.

What You’ll Need

  • Google Chrome (latest version) for DevTools and Lighthouse
  • Access to your website’s code (HTML, CSS, JavaScript files) — at least via a code editor or CMS that lets you edit scripts
  • A staging or test environment to try changes without breaking production
  • Optional: a PageSpeed Insights account (free) for lab data

Step-by-Step

  1. Open DevTools Performance panel. In Chrome, press F12 or right-click > Inspect. Go to the “Performance” tab. Click the circular record button, reload the page, and stop recording after the page fully loads. This gives you a trace of all network requests, JS execution, and rendering.
  2. Identify your worst Core Web Vital. In the same DevTools, go to the “Lighthouse” tab (or run Lighthouse in PageSpeed Insights). It will score LCP, INP (or FID if you’re on an older version), and CLS. Note which one is red or orange — that’s your priority.
  3. Measure LCP (Largest Contentful Paint). In the Performance trace, look for the largest image or text block. If it’s an image, check its loading priority. In DevTools, go to the “Network” tab, filter by “Img”, and see if the LCP image is delayed by a JavaScript-loaded slider or lazy-loading. If it’s text, check if a web font is blocking rendering.
  4. Fix LCP by preloading and deferring. Add <link rel="preload" as="image" href="your-lcp-image.jpg"> to the HTML head. For text, ensure your CSS is inlined or small, and use font-display: swap in your @font-face rule. Remove any JavaScript that hides or swaps the LCP element until after load.
  5. Measure INP (Interaction to Next Paint). In the Performance trace, click on a user interaction (like a click or keypress) and look for long “Task” blocks in the Main thread. These are JavaScript functions that block the UI. The longer the task, the worse the INP.
  6. Fix INP by breaking up long tasks. Split large synchronous functions into smaller chunks using setTimeout() or requestIdleCallback(). For example, if you’re processing a list of 10,000 items, process 1,000 at a time with a small delay between. Also, move non-critical JS to load after the page is interactive using defer or async attributes on script tags.
  7. Measure CLS (Cumulative Layout Shift). In the Performance trace, look for layout shifts (red bars in the “Experience” section). In DevTools, go to the “Rendering” tab and enable “Layout Shift Regions” to see exactly which elements move.
  8. Fix CLS caused by JS. The most common JS-induced CLS is from injecting content (ads, banners, embeds) without reserving space. Always set explicit width and height attributes on images and videos. For dynamic content, use CSS aspect-ratio or a min-height on the container. If you’re inserting content after load, wrap it in a container with a fixed height or use content-visibility: auto.
  9. Remove or defer third-party scripts. Many analytics, chat widgets, and ad scripts are heavy. In the Network tab, sort by “Total Size” and see which third-party scripts are largest. Defer them with async or load them only on user interaction (e.g., after a scroll or click). If a script isn’t essential, remove it entirely.
  10. Re-test after each change. After applying a fix, run Lighthouse again in incognito mode (to avoid extension interference). Compare scores. Iterate until all three vitals are in the green zone (LCP < 2.5s, INP < 200ms, CLS < 0.1).

Common Mistakes

  • Testing on a fast machine only. Your dev machine is often faster than a typical user’s phone. Always test on a mid-range Android device via PageSpeed Insights or DevTools device emulation with CPU throttling (set to 6x slowdown).
  • Ignoring the impact of fonts. Web fonts can block rendering and delay LCP. If you self-host fonts, use font-display: swap and preload the most critical font file.
  • Over-optimizing LCP and breaking INP. Preloading too many resources can clog the network and increase INP. Only preload the LCP element, not everything.
  • Using CSS to hide layout shifts instead of fixing them. Hiding a shifted element with visibility: hidden still counts as a shift if it moves later. Reserve space instead.
  • Not measuring in real user conditions. Lab tools (Lighthouse) are useful, but they don’t capture real-world network variability. Use the Chrome User Experience Report (CrUX) in PageSpeed Insights to see field data.

Tips

  • Use the “Performance insights” panel in DevTools (newer versions) — it highlights exactly which JavaScript functions are slow.
  • Set up a performance budget: e.g., total JS bundle < 300KB, no script over 50KB should block rendering.
  • Use import() to dynamically load JavaScript only when needed (code splitting). For example, load a carousel script only when the user scrolls to it.
  • For CLS, always include width and height attributes on images, even if you override them with CSS. This prevents layout jumps.
  • Consider using a service worker to cache your JavaScript and CSS, which speeds up repeat visits and reduces LCP.

Troubleshooting

  • Lighthouse shows a low score but the site feels fast. This often happens because Lighthouse runs on a simulated slow connection. Check the “Field Data” tab in PageSpeed Insights — if real users are fine, your lab score may be too pessimistic. Still, try to reduce JS execution time.
  • INP is still high after breaking up tasks. The issue might be a third-party script that runs on every click. Use the Performance trace to see if a specific event listener is causing the delay. If so, remove or replace that script.
  • CLS persists after setting dimensions. Check if you’re using CSS animations that change layout (e.g., animating width/height). Animate transform instead, which doesn’t trigger layout shifts.
  • Preload doesn’t improve LCP. If the image is still slow, it might be because the server is slow to respond. Use a CDN or optimize the image format (WebP/AVIF) and compress it.
  • Changes don’t appear in PageSpeed Insights. Clear your cache and use a fresh URL. Also, ensure you’re testing the same page that you changed — sometimes you’re looking at a cached version.

Frequently Asked Questions

What is a good Core Web Vitals score?

For the 75th percentile of users: LCP under 2.5 seconds, INP under 200 milliseconds, and CLS under 0.1. Anything better is excellent; worse needs fixing.

Do I need to fix all three vitals at once?

No. Prioritize the one that’s failing the most. Usually LCP is the easiest to fix, but INP is often the most impactful for user experience. Fix them one at a time and re-test.

How do I measure INP if I don’t have real user data?

Lighthouse 10+ simulates INP. For real data, use the Chrome User Experience Report (CrUX) in PageSpeed Insights, or add the web-vitals JavaScript library to your site to collect field data.

Can I fix CLS by just setting a min-height on the container?

Yes, if the content is injected asynchronously. But if the container is empty and then gets content, setting a min-height that matches the expected content size prevents the shift. Just be careful not to leave too much empty space.

Will removing third-party scripts hurt my analytics?

Not if you load them asynchronously or after user interaction. For example, load analytics after the page becomes interactive, or use a privacy-friendly alternative that’s lighter. Test your analytics still work after deferring.

How often should I re-test?

After every significant change to your JavaScript or layout. Also, monitor monthly via PageSpeed Insights to catch regressions from new features or dependencies.

Related

General steps for current mainstream versions; menus can differ by device and version. See the disclaimer or report an error.

More in this bed

The whole Tech How-To bed →