Blog
4 min read

How to Optimize Images for the Web: Formats, Sizes, and Lazy Loading

Images are usually the heaviest part of a page. Which format to use (WebP vs AVIF vs JPEG vs PNG vs SVG), how big to make them, responsive images with srcset, lazy loading done right, and the one image you should never lazy-load.

On most websites, images make up the majority of the bytes downloaded. A single 6 MB photo straight from a phone can make a page take ten seconds on mobile data. The good news: image optimisation is one of the easiest, biggest speed wins available.

The four rules

  1. Use the right format.
  2. Serve the right size.
  3. Compress.
  4. Load images only when they're needed — except the main one.

1. Choose the right format

Format Best for Notes
AVIF Photos Usually the smallest files at the same quality. Supported by all major current browsers.
WebP Photos and graphics Much smaller than JPEG/PNG, universally supported. A safe default.
JPEG Photos (fallback) Universal, but larger.
PNG Screenshots, images needing transparency Lossless and big for photos — don't use it for them.
SVG Logos, icons, simple illustrations A vector: tiny and sharp at any size.

WebP vs AVIF: AVIF typically compresses photos further than WebP, but takes longer to encode and some editing tools handle it less well. A practical approach: serve AVIF with a WebP fallback, or just use WebP everywhere — either is a big improvement on JPEG and PNG.

2. Serve the right size

A photo displayed 800 pixels wide doesn't need to be 4,000 pixels wide. Resize before uploading. A rough guide:

  • Full-width hero image: around 1,600–2,000px wide (to look sharp on high-density screens).
  • Content images: around 1,200px wide.
  • Thumbnails: a few hundred pixels.

Responsive images: different sizes for different screens

Phones don't need the desktop-size image. srcset lets the browser choose:

<img
  src="/photos/garden-1200.webp"
  srcset="/photos/garden-600.webp 600w,
          /photos/garden-1200.webp 1200w,
          /photos/garden-2000.webp 2000w"
  sizes="(max-width: 700px) 100vw, 700px"
  alt="A vegetable garden in early summer"
  width="1200" height="800">

sizes tells the browser how wide the image will display; it picks the smallest file that looks sharp.

Offer a modern format with a fallback

<picture>
  <source srcset="/photos/garden.avif" type="image/avif">
  <source srcset="/photos/garden.webp" type="image/webp">
  <img src="/photos/garden.jpg" alt="A vegetable garden" width="1200" height="800">
</picture>

3. Compress

Quality around 75–85 is usually indistinguishable from 100 at a fraction of the size. Free tools like Squoosh (in the browser) let you compare side by side. Build tools and image CDNs can compress automatically.

4. Lazy load — but not the main image

<img src="..." alt="..." loading="lazy" width="800" height="600">

loading="lazy" tells the browser to wait until an image is near the screen before downloading it. Great for images further down the page.

Never lazy-load the main image at the top of the page — the hero image or the product photo. It's usually your page's Largest Contentful Paint, and delaying it makes your page measurably slower. Instead, hint that it's important:

<img src="/hero.webp" alt="..." fetchpriority="high" width="1600" height="900">

See Core Web Vitals explained.

Always set width and height

Setting width and height (or a CSS aspect-ratio) reserves space before the image loads. Without it, text jumps down when the image arrives — that's layout shift, which annoys users and hurts your Core Web Vitals.

Don't forget alt text

Every meaningful image needs alt text describing it, for screen-reader users and search engines. Decorative images get alt="". See web accessibility basics.

Let your framework help

  • Next.js has an <Image> component that resizes, converts to modern formats, lazy-loads, and reserves space automatically. Mark the main image with the priority (or preload) prop, depending on your Next.js version.
  • Image CDNs can resize and convert on the fly from a URL.
  • User uploads should be resized on upload — never serve a 12 MB phone photo as a profile picture. See where should user uploads go?

The summary

  • Use WebP or AVIF for photos, SVG for logos and icons, PNG only when needed.
  • Resize to the displayed size and use srcset for different screens.
  • Compress to quality ~80.
  • Lazy-load below-the-fold images; prioritise the main one.
  • Always set width and height, and write alt text.

EasySpawn serves your app on your own domain with automatic SSL and lets Claude Code build and test image optimisation on the live site — not just in theory. See how it works or join the waitlist.

Related: Why Is My Website Slow? · What Is a CDN? · Core Web Vitals Explained · Responsive Design Basics

Keep reading