Speed teardown · Core Web Vitals

332 KB PNG → 28 KB WebP: a before/after teardown (68 → 95+ PageSpeed)

This exact page scored 68 on Performance. Five fixes — images, fonts, JavaScript, CSS and preloads — took it past 95 with zero design change. Here are the weights, the code and the checklist.

By PakWebDev·Oct 1, 2026·9 min read

The before/after in one table

WhatBeforeAfter
Logo payload (header + hero)332 KB PNG served twice3.3 KB + 28 KB WebP
Font weights loaded6 weights, render-blocking stylesheet3 weights, async
Hero image hintsNo size, no prioritywidth/height + fetchpriority + preload
Header costTranslucent blur over contentSolid white, zero blur
JavaScriptmousemove tilt on document, layout readsMenu + reveal only
PageSpeed Performance6895+
The headline numberImages alone removed ~300 KB from first load — more than every other fix combined. On a cheap Android on 4G, that is the difference between a 1-second and a 4-second paint.

Fix 1 — Right-size images, switch to WebP

The classic failure: one 500×500 PNG used for a 34-pixel header logo and a 300-pixel hero. The browser downloaded 332 KB to paint ~30 KB of pixels. The fix has three parts: generate each display size, serve WebP with a PNG fallback, and tell the browser the size up front so it can reserve space (no layout shift).

<picture>
  <source type="image/webp"
    srcset="/logo-420.webp 420w, /logo-500.webp 500w"
    sizes="(max-width:600px) 64vw, 300px">
  <img class="logo-hero" src="/logo-500.webp"
    alt="PakWebDev circular logo" width="420" height="420"
    fetchpriority="high" decoding="async">
</picture>

Results on this site: header logo 332 KB → 3.3 KB WebP, hero 332 KB → 28 KB WebP. The PNG fallback stays for ancient browsers but modern ones never touch it.

Fix 2 — Stop letting fonts block rendering

Google Fonts is fine; blocking Google Fonts is not. The old page loaded six weights (300–800) as a render-blocking stylesheet — the browser waited on a third party before painting text. Two changes: cut unused weights (body 300 → 400, keep 400/600/800) and load the stylesheet asynchronously:

<link rel="preload" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;600;800&display=swap" as="style" onload="this.onload=null;this.rel='stylesheet'">
<noscript><link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Inter+Tight:wght@400;600;800&display=swap"></noscript>

System fallbacks (system-ui, -apple-system, Segoe UI, Roboto) paint instantly; Inter Tight swaps in when ready. No invisible-text flash, no blocked first paint.

Fix 3 — Delete the cute JavaScript

The old page ran a mousemove listener on the whole document for a 3D logo tilt, plus per-row listeners doing layout reads. That is main-thread work on every pointer move — pure INP damage for decoration. We deleted it. What remains is a menu toggle and one IntersectionObserver reveal, both guarded:

Fix 4 — CSS: solid header, cheaper paint

Fix 5 — Preload what LCP needs, nothing else

<link rel="preload" as="image" href="/logo-420.webp" fetchpriority="high">

One preload for the LCP image. Everything else — OG images, manifest icons, footer links — loads lazily or on demand. Preloading more than the LCP asset just re-creates the congestion you removed.

How to measure (so your numbers are honest)

  1. Test the same URL in PageSpeed Insights, mobile, three runs, take the median.
  2. Record LCP, INP and CLS — not just the headline score.
  3. Re-test after each fix to attribute the gain; ship the winners together.
  4. Confirm in field data (CrUX) 28 days later — lab wins that don't survive real devices don't count.

Copy-paste checklist

FAQ

What was the single biggest speed win?

Images. Right-sized WebP cut ~300 KB from first load — more than fonts, JS and CSS combined.

Do Google Fonts hurt PageSpeed?

Only when render-blocking. Fewer weights plus an async stylesheet removes the block while keeping the design.

How should speed be measured?

PageSpeed Insights, same URL and throttling, three runs, median — tracking LCP, INP and CLS, then confirming with field data.

Want this teardown for your site?

Send your URL on LinkedIn — you get measured before/after numbers and a fixed scope. No forms, no queue.