Crux Read real markup, a click handler, and a web-vitals log line, predict the Core Web Vital that breaks, and pick the highest-leverage fix.
Your altitude — climbing toward senior
ZeroJuniorMiddleSenior
You are at senior altitude — in orbit
◷ 14 min
Vitals problems are diagnosed in markup, handlers, and the RUM log — not in a definition. Read each snippet, predict which vital breaks and why, then choose the fix a senior engineer makes first.
Goal
Practise the loop you run on every vitals regression: read the code or the attributed log line, predict which metric it hits, name the dominant phase or part, and reach for the fix that targets it — not the convenient one.
Snippet 1 — the un-sized hero
<!-- hero, the LCP element, injected after the article text --><section class="article"> <p>Paragraph one of the article…</p> <img src="/hero.avif" class="hero" alt="Product hero" /> <p>Paragraph two…</p></section>
.hero { width: 100%; } /* height auto, no intrinsic ratio known */
Quiz
Completed
What breaks here, which vital does it hit, and what is the fix?
Heads-up width: 100% sets the rendered width but supplies no height or intrinsic ratio, so the box is 0-height until the image loads. The HTML width/height attributes are what give the browser the ratio to reserve space.
Heads-up AVIF is a modern, efficient format; decode is not the issue. The defect is the missing dimensions causing a layout shift (CLS), not LCP load time.
Heads-up A static image does not block the main thread for interactions. The problem is the unreserved space causing a CLS shift when the image finally lays out.
The dimensions are correct, so CLS is fine — but LCP regressed after this attribute was added. Which attribute, and why?
Heads-up Dimensions prevent CLS and do not add LCP cost — they let the browser reserve space. The regression is loading='lazy', which delays the start of the hero's download.
Heads-up An oversized source hurts load TIME, but the described regression appeared when the attribute was added — that points at load DELAY from loading='lazy'. Both can be fixed, but lazy on the hero is the proximate cause.
Heads-up Lazy loading does nothing to render speed; it delays the start of the load. On the LCP element that directly delays the metric.
Snippet 3 — the click handler
button.addEventListener('click', () => { const filtered = hugeList.filter(matchesQuery); // ~180 ms, 50k items renderResults(filtered); // re-renders the list highlightActiveTab(); // tiny DOM update});
Quiz
Completed
INP on this button is ~210 ms even though the thread is idle when the user taps. Which INP part dominates, and what is the highest-leverage fix?
Heads-up The stem says the thread is idle at tap time, so input delay is near zero. The 180 ms cost is inside the handler — processing time — not a queue delay.
Heads-up The re-render contributes to presentation delay, but the dominant 180 ms is the synchronous filter in the handler (processing time). Move that off the critical path first.
Heads-up Good INP is ≤200 ms at p75; 210 ms is over the threshold. And a 180 ms synchronous handler is a clear, fixable processing-time problem.
Reading this attributed RUM line, which fix is correct and what should you NOT do?
Heads-up TTFB is a small slice next to a 3510 ms loadTime. The phase split is decisive — fix the dominant phase, which is resource load time.
Heads-up Both are well within 'good' (INP ≤200 ms, CLS ≤0.1). The only poor metric here is LCP, driven by image load time.
Heads-up Preload targets discovery/load delay, not renderDelay — and loadDelay is already 90 ms. The dominant phase is loadTime; shrink the image instead.
Recap
Every vitals regression is read in code or an attributed log: an img without width/height is a CLS shift; loading=‘lazy’ on the hero is a self-inflicted LCP load-delay regression; a heavy synchronous handler is INP processing time you move off the critical path with startTransition or scheduler.yield; and a web-vitals line’s phase split tells you which LCP phase to fix and which fix would be wasted. Read the attribution first, fix the dominant phase or part, then re-measure to confirm.