/guides/website-speed-optimization · Performance · 17 min read

In-depth guide

Website Speed Optimization: The Engineer's Guide

Every second of load time on a small business website deletes conversions and rankings. This guide is the exact playbook we use to ship sites that score 95–100 on Core Web Vitals — even on a mid-tier phone with a weak cellular signal.

Updated January 15, 2026By Hulsey Creative Co.

Core Web Vitals — the three metrics that matter

Google measures user-perceived speed with three metrics. All three feed into rankings and all three are visible in your Search Console:

  • LCP (Largest Contentful Paint) — how long until the largest above-the-fold element paints. Target: under 2.5s.
  • CLS (Cumulative Layout Shift) — how much the page jumps around while loading. Target: under 0.1.
  • INP (Interaction to Next Paint) — how quickly the page reacts to a tap or click. Target: under 200ms.

Fixing LCP

LCP is almost always dominated by one element: a hero image, a hero heading, or a hero video. Optimizations, in order of impact:

  1. Serve the hero image in a modern format (AVIF or WebP), correctly sized for the viewport.
  2. Preload the hero image with <link rel="preload" as="image">.
  3. Never lazy-load the hero. Lazy-load everything below the fold.
  4. Inline the CSS needed for the first paint; defer the rest.
  5. Cut render-blocking JS out of the head. If you can't remove a script, mark it defer or async.

Fixing CLS

CLS is caused by content moving after it has painted. The three usual culprits: images without dimensions, web fonts that swap, and injected iframes/ads.

  • Always set width and height (or aspect-ratio) on <img> and <iframe>.
  • Preload critical fonts and use font-display: optional or a size-adjust @font-face fallback.
  • Reserve space for banners, cookie notices, and embeds with a fixed min-height.

Fixing INP

INP replaces FID as of March 2024. It measures the actual latency of interactions, not just the first one, and it is brutally honest about JavaScript-heavy sites.

  • Break long tasks. Anything over 50ms on the main thread degrades INP.
  • Defer non-critical third-party scripts (chat widgets, analytics, tag managers) until after user interaction.
  • Use requestIdleCallback for background work.
  • Prefer CSS transitions and CSS view transitions over JS animation libraries.

Fonts

Web fonts are the most commonly-mishandled asset on small business sites. Self-host them, preload the two or three weights you actually use, subset to Latin unless you need more, and always define a font-family fallback stack that visually matches so swap-in is invisible.

Images

  • AVIF for photos when browser support allows, WebP as fallback, JPG only as last resort.
  • Generate a srcset with 2–3 widths (e.g., 640, 1024, 1600) and use sizes to tell the browser which to pick.
  • Compress aggressively — mozjpeg quality 75 or AVIF quality 60 is almost always indistinguishable.
  • Lazy-load everything below the fold with loading="lazy" and decoding="async".

Compression, caching, and CDNs

Brotli compression is table stakes for HTML, CSS, and JS. HTTP caching headers should be aggressive on hashed assets (Cache-Control: public, max-age=31536000, immutable) and shorter on HTML (max-age=0, must-revalidate). A CDN is not optional for a business that serves customers across a region — it moves the bytes physically closer to the visitor and terminates TLS at the edge.

JavaScript and CSS discipline

  • Ship less JS. Every KB of client-side JS is a tax on INP and LCP.
  • Server-render as much as you can. Hydrate only what needs interactivity.
  • Route-split — never load the shopping cart JS on the About page.
  • Purge unused CSS (Tailwind's JIT and Lightning CSS do this automatically).
  • Kill jQuery, Bootstrap JS, and legacy carousel libraries. Native equivalents are lighter and faster.

The speed optimization checklist

  1. Run Lighthouse and PageSpeed Insights on a real mobile profile.
  2. Identify the LCP element and preload it.
  3. Serve hero images as AVIF or WebP with srcset.
  4. Set explicit dimensions on every image and iframe.
  5. Self-host and preload critical fonts.
  6. Defer or async every non-critical script.
  7. Enable Brotli compression at the edge.
  8. Set long cache headers on hashed assets.
  9. Deploy behind a global CDN.
  10. Retest on a real device — not just DevTools.

// Frequently asked

Questions people ask about Speed.

  • What are Core Web Vitals?
    Core Web Vitals are Google's three user-experience metrics: LCP (paint speed), CLS (layout stability), and INP (interaction responsiveness). Together they feed into Google's ranking algorithm and are the industry standard for measuring perceived site performance.
  • What is a good LCP score?
    Under 2.5 seconds on a mid-tier mobile device on a 4G connection is Google's "good" threshold. Under 1.8 seconds is where our sites typically land.
  • Do I really need a CDN for a small local website?
    Yes, if you serve customers across a region or state. A CDN moves your files physically closer to the visitor, terminates TLS at the edge, and absorbs traffic spikes. Modern CDNs cost pennies for a small site.
  • Should I use lazy loading on hero images?
    No. Lazy-load everything below the fold, but the LCP element (usually the hero) must load eagerly — often with an explicit <link rel="preload">. Lazy-loading the hero is one of the most common self-inflicted speed wounds.

Want this built into your site?

We ship the guides we write.

Every principle in this guide is baked into every website we build. Request a callback and we'll walk your current site against these standards, line by line.

Free website report card →