Start a project

Article · Web performance · Core Web Vitals · 12 min read

How to diagnose Core Web Vitals issues

Diagnosing a Core Web Vitals problem means finding the element or the interaction that is failing, then reading a trace or a waterfall until you can name the delay. A Lighthouse score, a red CrUX cell, or a single lab run is a symptom. It is not a diagnosis. The useful work is to separate lab from field, to treat LCP, INP and CLS as different questions, and to fix the bottleneck you actually measured, in that order.

On this page 10 sections
  1. Lab, field and the question you are asking
  2. LCP: find the element, then the delay
  3. INP: the click, the work, the paint
  4. CLS: reserved space and late font swaps
  5. Reading a Lighthouse report without getting lost
  6. Reading a Chrome trace and a HAR waterfall
  7. A fix order that starts with the real bottleneck
  8. When the lab looks fine and the field does not
  9. Key takeaways
  10. Frequently asked questions

I use the same habit here that I use when finding iOS performance problems with Instruments: open a recording, find the expensive interval, and only then change the code. The tools on this site — the Core Web Vitals Calculator, the Lighthouse Report Diff, the Chrome Trace Viewer, the HAR Waterfall Analyser and the CLS Simulator — are there to support that sequence, not to decorate a report.

Lab, field and the question you are asking

Lab data is a test you ran: Lighthouse, a WebPageTest run, a trace on your machine, often on a fast connection with a warm or a forced-slow CPU. It is repeatable, and it is excellent at telling you what blocked this particular load. It is not a promise about how the site feels for everyone else.

Field data is what real visits did: the Chrome User Experience Report (CrUX), Search Console’s Core Web Vitals report, or your own RUM. Google uses field data, at the 75th percentile, when it assesses the Core Web Vitals of a page or an origin. A page can pass the lab and fail in the field, or the reverse.

As of November 2026, the Core Web Vitals and the commonly cited “good” thresholds, measured at the 75th percentile of visits and documented on web.dev’s Web Vitals guide, are:

Those thresholds and even the set of metrics can change. Confirm them on that page, or in Google’s Search documentation, before you treat a number as a target in a year’s time. The Core Web Vitals Calculator will classify a measured value against the thresholds you give it; it does not replace the official definitions.

Start every investigation by writing down which data set is failing, on which URL or origin, on mobile or desktop, and since when. “The site is slow” is not a question you can instrument.

LCP: find the element, then the delay

LCP is the time from the start of the load until the largest content element in the viewport is painted. On many article and marketing pages that element is a hero image, a heading, or a large text block. Until you know which element it was, you are guessing.

In the field, use a web-vitals attribution build, CrUX debug info where you have it, or a RUM beacon that records the LCP element. In the lab, Lighthouse and a performance trace will usually name a candidate, but a different viewport can pick a different element, so match the viewport to the report you are explaining.

Once you have the element, split the time into the usual parts, as web.dev’s LCP documentation describes them:

Fix the part that is actually long. Compressing an image will not help if the HTML took four seconds to arrive, and a new CDN will not help if the hero is only inserted after a client-side fetch. For image-heavy LCP, the responsive images guide is the next stop.

INP: the click, the work, the paint

INP looks at the latency of real interactions — clicks, taps, key presses — across the visit, and reports a high percentile of them, not only the first input. A page that is quiet until someone opens a menu can look fine in a load-only lab test and fail INP in the field.

When an interaction is slow, split it into three intervals:

The field will tell you that INP is high, and sometimes which element was involved. A performance trace of the same interaction, recorded on a realistic device or a throttled CPU, will show the long task. Look for scripts you did not know ran on every pointer event, for handlers that do work that could wait until after paint, and for third parties that attach themselves to every click.

A page can also fail INP because of an overlay, a cookie banner, or a chat widget that people actually touch. If the failing element is not “yours”, it is still your page’s metric. Removing or deferring that third party is a real fix, which is why a performance budget should name those scripts before they land.

CLS: reserved space and late font swaps

CLS measures unexpected layout shifts in the viewport. A shift is expected if it follows a user action, within a short window; it is unexpected if the page moves while the person was still looking at it.

The usual causes are mundane:

The CLS Simulator is a way to build an intuition for how large a shift is. For a live page, a lab trace with layout-shift regions, or the Performance panel’s experience track, will highlight the nodes that moved. Reserve the space in the first HTML and CSS, or load the late UI in a reserved slot, rather than “just sliding it in”.

Web fonts deserve a deliberate choice, not a copy-pasted swap on a display face that changes line count. If you can use a fallback with similar metrics, or preload a small, critical face, you often get both readable text and a quieter layout. This is a milder version of the work I describe in optimising battery efficiency on iOS: the cost is not only the download, it is the work and the disruption after the download arrives.

Reading a Lighthouse report without getting lost

Lighthouse is a lab test with a specific device profile, a specific network assumption, and a score that mixes many audits. It is useful, and it is noisy.

How I read it:

  1. Note the mode (mobile or desktop), the Lighthouse version, and whether the run was on a production URL with a clean cache. A staged host with debug scripts is not the live page.
  2. Look at the LCP element, the main-thread long tasks, and the layout-shift items before you look at the 0–100 performance score.
  3. Treat opportunities as candidates, not as a to-do list in the order shown. “Reduce unused JavaScript” on a 4 KB file is not the priority if TTFB is 3 seconds.
  4. Re-run once or twice. A single run can be an outlier. The Lighthouse Report Diff is useful when you want to see whether a change moved a metric, or only the score of an unrelated audit.
  5. Do not chase a 100. Use the report to form a hypothesis, then confirm it in a trace and, when you can, in the field.

Search Console may show a URL group rather than the exact page you tested. Diagnose a representative URL, but remember that a template problem (a hero on every article) will not be fixed by editing one popular post.

Reading a Chrome trace and a HAR waterfall

When you have a hypothesis, record the evidence.

A HAR waterfall shows the network: when each request started, how long DNS, connect, TLS, waiting and download took, which requests were blocked, and which were redirected. The HAR Waterfall Analyser is a way to read that file without squinting at a raw JSON export. For LCP, you want to see when the HTML arrived, when the LCP resource was first requested, and what else was on the wire at the same time. For slow APIs, you want the waiting time, not only the file size. Caching mistakes show up here too; the HTTP caching headers guide is the companion piece if every visit refetches the world.

A Chrome performance trace shows the main thread: parsing, compile, long tasks, style, layout, paint, and, with the right settings, layout shifts and LCP markers. The Chrome Trace Viewer will open a trace you already captured. Look at the interval between the interaction and the next paint for INP, or at the gap between the LCP resource finishing and the LCP event. A 200 ms download followed by a 800 ms long task is a render-delay problem, not a “needs a smaller JPEG” problem.

Capture the trace on a throttled CPU if you are explaining a mobile field failure. A quiet desktop profile will hide the long task that a mid-range phone shows you immediately.

A fix order that starts with the real bottleneck

Once you can name the metric, the element or interaction, and the delay, fix in this order:

  1. The current bottleneck only. If LCP is waiting on HTML, do not start by rearranging CSS classes. If INP is a third-party click handler, do not start by rewriting your typography.
  2. The first response. Server time, redirects, and HTML that already includes the LCP image or heading will help more than a fine-tuned client bundle if the document is late or empty.
  3. The LCP resource. Discover it early, size it correctly, serve a modern format, and avoid lazy-loading the LCP image.
  4. Main-thread work that blocks paint or input. Break up long tasks, defer non-critical scripts, and be honest about third parties.
  5. Reserved space and fonts for CLS, once the page is otherwise painting on time.
  6. Re-measure in the same lab conditions, then wait for field data to move. Field percentiles lag, and a handful of visits will not flip a CrUX cell.

A performance budget is how you stop the same third party from walking back in next month. Diagnosis is how you decide what the budget should constrain.

When the lab looks fine and the field does not

This is common, and it is not a reason to ignore the field.

Typical explanations:

When the field looks fine and the lab does not, check that you tested the production URL, that a debug build is not being measured, and that the lab profile is not an extreme you would never see. Then decide whether the lab is still telling you about a real risk, for example a long task that will show up as INP once more people start clicking.

Do not average the two data sets into a compromise score. Answer the field question for the people who already visit, and use the lab to inspect the cause.

Accessibility and performance also meet here. A page that jumps, or that ignores a tap for half a second, is harder to use, in the same spirit as designing accessible interfaces. Fixing the cause of the metric usually helps the person, which is the point of the metric.

Key takeaways

If you want a second pair of eyes on a Core Web Vitals report that will not tell you what to fix, tell me about it.

Frequently asked questions

What is the difference between lab and field Core Web Vitals?

Lab data is a test you ran, under conditions you chose. Field data is what real visits experienced, usually reported at the 75th percentile. Google’s Search assessment uses field data. The lab is still the best place to see a trace of the delay, as long as you remember it is not the same as the field.

How do I find what is slowing LCP?

Identify the LCP element, then split the time into time to first byte, how late the resource was discovered, how long it took to download, and how long it waited to paint. A waterfall and a performance trace will show which of those is long. Fix that part first, rather than applying every image tip at once.

What causes a high INP score?

A slow interaction: the main thread was busy when the person clicked, the handler did too much work, or the next paint was delayed. Third-party scripts, hydration, and heavy menus are common sources. You need a trace of the interaction, not only a load-time Lighthouse run, to see which interval is at fault.

How do I debug layout shift (CLS) on a live page?

Record a performance trace or use a layout-shift visualisation, and note the nodes that moved. The usual fixes are width and height (or aspect-ratio) on media, reserved space for banners and embeds, and font-fallback metrics that do not change the size of the text. The CLS Simulator on this site is a way to understand the score; the live page still has to show you the node.

Should I trust Lighthouse or CrUX more?

They answer different questions. Trust CrUX, or your own RUM, for whether real visits meet the current thresholds. Trust Lighthouse, a trace and a waterfall for why a particular load or interaction was slow. When they disagree, explain the disagreement; do not pick the more flattering one.

Written by Lee Johnson. Published 10 November 2026.

All articles · Swift A–Z · Apps

Questions, or an app in mind?

Let's bring your ideas to life. Whether you're envisioning a game-changing Apple Watch app or a transformative iOS experience, I'm here to make it happen.

Start a project