From £45/month on EU-sovereign UK hosting. Cancel any time.

From £45/mo · EU-sovereign · Cancel any time

See the three tiers →

Core Web Vitals under 1s: what gets LCP under 1s on a UK SMB site

Waterfall diagram showing a 0.71s LCP build: HTML 80ms, preconnect 120ms, AVIF hero 540ms, font subset parallel.

The /systems page commits to LCP under 1 second, INP under 200ms, CLS under 0.05, and Lighthouse Performance ≥ 95 — measured on 4G throttled mobile. The previous post on this thread, the 0.05-second test, explains why those numbers matter (every second past one is roughly 32% of mobile visitors gone). This piece is how the numbers get hit.

The benchmark is a real Leeds clinic rebuild, late May 2026. The old Wix site clocked LCP at 4.8 seconds on a Moto G4 / 4G WebPageTest profile. The rebuild, hosted on Vercel London (lhr1), shipped at 0.71 seconds on the same profile. The techniques below are the diff.

What 4G throttled mobile actually means

Before the techniques: the test profile, because “fast” is meaningless without one.

WebPageTest’s “Mobile - Slow 4G” profile is 1.6 Mbps down, 750 Kbps up, 150ms RTT, throttled CPU at 4× Moto G4 (a 2016 Android device with two underclocked Cortex-A53 cores). That’s not the median UK 4G connection in 2026 — it’s roughly the worst tenth percentile. Google’s Core Web Vitals reporting in Search Console uses field data weighted toward the slower end. So a site that hits LCP < 1s on this profile will hit it consistently in the field.

The Vercel London location matters because every TCP round-trip from a UK visitor to lhr1 is roughly 5-20ms. Every round-trip to AWS US-East-1 is 70-120ms. Eight round-trips at 100ms each is 800ms of LCP gone before a single byte arrives. That’s the entire LCP budget, spent on packets that crossed the Atlantic for no reason.

Technique 1 — image priority hints

The single biggest LCP lever on any UK SMB site is the hero image. Browsers don’t know which image is the hero — they treat all <img> tags the same. The fetchpriority="high" attribute tells the browser “this one, before everything else.”

<img
  src="/hero.avif"
  alt="Leeds clinic exterior — Victorian sandstone, brass plate signage."
  width="1600"
  height="900"
  fetchpriority="high"
  decoding="async"
/>

Three things in that snippet matter. fetchpriority="high" moves the image to the front of the queue. width and height prevent the layout shift that would otherwise tank CLS. decoding="async" lets the browser paint the rest of the page while decoding finishes.

The discipline is exactly one fetchpriority="high" per page. Two high-priority images mean neither is high-priority. The hero gets it; everything else doesn’t.

Technique 2 — AVIF originals, under 60KB

Hero images in 2026 should be AVIF. Not WebP, not JPEG. AVIF compresses 30-50% smaller than WebP at equivalent perceptual quality, and browser support is 95%+ in mid-2026. The fallback path is <picture> with a JPEG <source> for Safari iOS < 16, but for most UK SMB audiences a single AVIF works.

Target file size for the hero AVIF: under 60KB. A 1600×900 hero at quality 60 typically lands at 35-50KB. Anything over 80KB and the LCP budget is hostage to the file size, not the CDN.

Pipeline: source PNG/JPG → sharp or avifenc → quality 60-65, speed 4 → ship. UK Web Marketing builds run the conversion at build time via Astro’s image service, so the AVIF is generated once per content change, not on every request.

Technique 3 — preload the hero, preconnect the third-party

Two <link> tags in <head> that save roughly 200-400ms each:

<link
  rel="preload"
  as="image"
  href="/hero.avif"
  type="image/avif"
  fetchpriority="high"
/>
<link rel="preconnect" href="https://plausible.io" crossorigin />

The first tells the browser to start downloading the hero while the HTML is still being parsed, instead of waiting until the parser reaches the <img> tag. On a 4G connection, that overlap saves a full round-trip — often 150-250ms.

The second opens a TCP + TLS connection to the one third-party domain that survived the audit (in our case, Plausible Analytics) before the script tag for it gets parsed. Saves another 100-200ms when the analytics request fires.

Two tags, ~400ms back in the LCP budget. The discipline is not adding more. Every additional preconnect costs DNS + TLS setup capacity; three preconnects starts harming the priority of the hero itself.

Technique 4 — critical CSS inlined under 14KB

The 14KB number is not arbitrary. It’s the size of the initial TCP congestion window (initcwnd = 10 segments × ~1460 bytes per segment ≈ 14KB) — the amount of data the server can send in the first round-trip before waiting for an ACK. CSS that fits in that first window arrives in one round-trip; CSS that doesn’t, doesn’t.

The technique: inline the CSS needed to render above-the-fold into <head>, defer the rest. Astro’s astro:assets and the Critical plugin both automate this. Hand-rolled, the rule is: a stylesheet over 14KB needs splitting into a critical block (inlined) and a non-critical block (<link rel="stylesheet"> with media="print" onload="this.media='all'" to defer).

Target: critical CSS at 8-12KB gzipped. Below 8KB is rare and usually means the design is missing rules; above 14KB is a budget overrun.

Technique 5 — font subsetting to a single Latin file

A standard variable font ship is 80-180KB. A subsetted Latin file with the actual glyphs the site uses is 22-32KB. The 100KB saving is roughly 500ms on a 4G connection.

The technique is glyphhanger or fonttools subset to produce a .woff2 containing only latin and latin-ext ranges. Then load with font-display: swap so text renders in a system fallback until the custom font arrives:

@font-face {
  font-family: "Inter";
  src: url("/fonts/inter-latin.woff2") format("woff2");
  font-display: swap;
  font-weight: 100 900;
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC,
                 U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074,
                 U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215;
}

font-display: swap is the one that matters. The LCP element is usually text, not the hero image, on content-heavy pages — and font-display: block (the historical default) would make LCP wait for the font, which costs you the entire technique. swap renders the text in fallback immediately and re-paints when the custom font lands.

Technique 6 — zero render-blocking JavaScript

The hardest rule, and the one that distinguishes a real performance posture from a stated one.

By default, every <script src="..."> in <head> blocks rendering until the script downloads, parses, and executes. On a UK SMB site, the typical render-blocking scripts are: Google Analytics, a chat widget, a cookie consent banner, a “back to top” button, a hero carousel.

UK Web Marketing builds ship zero render-blocking JS by default. The techniques:

  1. Analytics is defer-loaded. Plausible’s snippet is <script defer data-domain="..." src="..."></script>. The defer attribute moves execution to after the HTML parser finishes — never blocking render.
  2. Chat widgets are excluded. No Intercom, no Drift, no Tidio loaded by default. If a client wants chat, it’s an opt-in island that loads on a user action.
  3. Cookie banners are server-rendered. Because the site doesn’t use cookies for tracking (Plausible is cookieless), there’s no banner to load. Why your UK clinic website probably breaks GDPR covers the posture.
  4. Hero carousels are CSS-only or replaced with static heroes. A JS carousel ships 30-80KB of render-blocking work for a feature 6% of visitors interact with. Static hero is the default.
  5. Astro islands are client:visible. Interactivity hydrates only when the component scrolls into view, never on initial render.

The cumulative effect: a typical Foundation-tier page ships under 40KB of JS, deferred, on the entire page. Compared to a Wix site shipping 1.4-2.8MB of JS, half of it render-blocking, the LCP difference isn’t a tuning question — it’s a different category of artefact.

Technique 7 — where INP goes to die

A 200ms INP budget is generous if the page has no hydration cost. It evaporates the moment a hydration-by-default framework is in the stack.

The typical INP killer in 2026 is a Next.js Pages Router site (pre-App Router) that hydrates the entire page tree on load. On a Moto G4, hydrating a moderately complex page tree takes 280-540ms. Every interaction in that window is queued behind the hydration work — so the first click after page load sees an INP of 300-500ms, well above the 200ms threshold.

The fix is architectural, not tactical: pick a static-first framework. Astro hydrates only the islands you mark client:*. The default page tree has zero hydration cost. INP on a typical Foundation site lands at 40-90ms, with the entire budget for the actual interaction, not the framework warming up.

This is also why React Server Components matter in 2026 — they let Next.js sites ship more zero-hydration HTML, narrowing the gap. Astro is still ahead on the default case.

The cold-cache measurement that matters

The number that matters is the cold cache render — first visit, no service worker, no cached assets. Hot-cache LCP is usually 200-400ms regardless of build quality, because everything is already in memory. Cold cache is the visitor’s first impression.

Leeds clinic rebuild, May 2026, cold cache, Moto G4 / 4G:

  • LCP: 0.71s (target < 1.0s)
  • INP: 64ms (target < 200ms)
  • CLS: 0.01 (target < 0.05)
  • Lighthouse Performance: 99 (target ≥ 95)
  • Total page weight: 188KB (HTML 18KB, CSS 11KB inlined, AVIF hero 42KB, Latin font 28KB, JS 36KB deferred, favicon + meta 53KB)

The previous Wix site on the same profile: LCP 4.8s, INP 412ms, CLS 0.34, Lighthouse Performance 31, total page weight 4.6MB.

What this means commercially

The performance budget is a feature, not a vanity metric. On Google’s own data, the difference between a 1-second and a 6-second LCP is roughly half the mobile visitors who would have stayed. For a Leeds plumber paying for AdWords clicks at £3.50 a click, half is the difference between profitable and unprofitable.

The seven techniques above are the Foundation tier default. They don’t cost extra. They’re not an optimisation pass at the end of the build — they’re the way the build ships.

If you want to know what your current LCP looks like: free site audit. If you want the techniques applied to your site: managed website service.

Related: 0.05 seconds — the test your website is failing, Why your website is costing you work, Should I just build on Wix?.

Keep reading

← All articles

Three honest tiers · From £45/mo · Cancel any time

Ready for the website + infrastructure your business should already have?

Start your build
Start your build — £45/mo WhatsApp