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
- Use the right format.
- Serve the right size.
- Compress.
- 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 thepriority(orpreload) 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
srcsetfor 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
How to Turn Your Web App Into a Mobile App (Without Rebuilding It)
Three realistic paths from a web app to a phone app: make it a PWA, wrap it with Capacitor for the App Store and Google Play, or rebuild with React Native. Costs, what Apple rejects, what you need (yes, a Mac), and how to choose.
robots.txt and sitemap.xml Explained: A Beginner's Guide
Two small files that tell search engines (and AI crawlers) what to crawl and what exists on your site. How robots.txt and sitemap.xml work, examples, the robots.txt mistake that hides your whole site, why Disallow doesn't remove pages from Google, and how to generate both in Next.js.