AniUI Academy

Core Web Vitals, Images, and Fonts

LCP, INP and CLS as the actual scoring rubric behind 'is this page fast,' and the concrete image and font loading strategies that move each metric.

12 min read

"Is this page fast?" used to be a subjective question. Core Web Vitals turned it into three specific, measured metrics — Largest Contentful Paint (LCP), Interaction to Next Paint (INP), and Cumulative Layout Shift (CLS) — each targeting a distinct failure mode a user actually feels, and each with its own concrete set of causes and fixes.

LCP — Largest Contentful Paint

How long until the largest visible element (usually a hero image or a headline) finishes rendering. Answers: 'does this feel like it loaded?'

INP — Interaction to Next Paint

How long between a user interaction (click, tap, keystroke) and the next visual update reflecting it. Answers: 'does this feel responsive?'

CLS — Cumulative Layout Shift

How much visible content unexpectedly moves during the page's lifetime. Answers: 'does this feel stable, or does it jump around?'

LCP: what's slow, and image strategy

LCP is tied to one specific element — usually a hero image, sometimes a large text block — so improving it means directly targeting whatever delays that element's render. Concrete levers: preload it with <link rel="preload" as="image"> if it isn't discoverable early in the HTML (a background image set via CSS, for instance, is discovered later than an <img> tag); never lazy-load an above-the-fold imageloading="lazy" defers the very request LCP is waiting on, which is exactly backwards for the one image most likely to be the LCP element; serve appropriately sized and modern-format images (responsive srcset, AVIF/WebP) so the bytes that have to arrive before that element can render are as few as possible; and avoid burying the LCP image's request behind other, less important requests in the loading order.

INP: what's slow, and the main-thread problem

INP replaced First Input Delay specifically because FID only measured the delay before an interaction started being processed — INP measures the full latency through to the next visual update, which is a closer match for what a user actually experiences as "did my click do anything." A poor INP almost always traces back to the main thread being busy: a heavy synchronous computation, an expensive re-render triggered on every keystroke or click, a large event handler doing too much work before yielding. The fixes are about reducing or deferring that work — debouncing expensive operations, virtualizing large result lists so a keystroke doesn't re-render thousands of DOM nodes, breaking up long tasks so the browser can paint in between, and moving genuinely heavy computation off the main thread (a Web Worker) where that's viable.

CLS: what's slow, and font/image dimension strategy

CLS is caused by content moving in ways the user didn't trigger — most commonly, an image or ad slot whose final size wasn't known ahead of time, so surrounding content shifts once it loads and its real dimensions become known. The direct fix: always specify width and height (or aspect-ratio) on images, so the browser reserves the correct space during layout, before the image itself has arrived.

Fonts cause a related but distinct shift: if a custom web font loads after initial paint, and its metrics (character width, line height) differ from the fallback font shown first, text re-flows once the real font swaps in — visible as a jump in headings or paragraphs. font-display: optional or swap control this behavior, and matching the fallback font's metrics as closely as possible (some tooling can generate a metrically-adjusted fallback automatically) minimizes the visible jump when the real font does arrive.

Why the specific metric matters, not just "fast"

Each of these three metrics is genuinely independent — a page can have excellent LCP and terrible INP (fast to look done, unresponsive when touched), or excellent INP and terrible CLS (responsive, but jumpy). Naming which specific metric is the actual problem, and which specific mechanism is causing it, is the difference between a targeted fix (preload the hero image; reserve space for that ad slot; debounce that search input) and generic advice that may not touch the actual bottleneck at all.

What to remember

  • LCP, INP and CLS each measure a distinct, user-felt failure mode: slow-to-load, unresponsive, and jumpy, respectively.
  • LCP is tied to one specific element — target its discovery and download directly; never lazy-load it.
  • INP traces back to main-thread work blocking the response to an interaction — reduce, debounce, or defer that work.
  • CLS comes from content whose final size wasn't reserved ahead of time — explicit image dimensions and careful font-loading strategy are the direct fixes.

Check yourself

3 questions · pass 3/3 to unlock Why and When to Split a Frontend

up to 50
  1. 1.A product page's largest element is a hero image that only starts downloading after a render-blocking font and several other images higher in the document have loaded. Which Core Web Vital does this most directly harm, and why?

  2. 2.Why does omitting width and height attributes (or an aspect-ratio) on an <img> tend to hurt Cumulative Layout Shift specifically?

  3. 3.A page's Interaction to Next Paint (INP) is poor specifically on a search-as-you-type input. What's the most likely direct cause?

3 left to answer