How Images Affect Website Speed
Images are the single biggest cause of slow websites. Here's exactly how they hurt your scores — and the optimization workflow that fixes it.
Table of contents
- How images hurt speed
- 1. They're huge
- 2. They block LCP
- 3. They cause layout shifts
- 4. They consume bandwidth on mobile
- The image optimization workflow
- Step 1: Use the right format
- Step 2: Resize to displayed dimensions
- Step 3: Serve responsive sizes
- Step 4: Set explicit dimensions
- Step 5: Lazy-load below the fold
- Step 6: Preload the LCP image
- Step 7: Use a CDN for image delivery
- Common image mistakes
- Mistake 1: Lazy-loading the LCP image
- Mistake 2: Using PNG for photos
- Mistake 3: Background images for hero content
- Mistake 4: Serving the same image to everyone
- Mistake 5: Not setting explicit dimensions
- Mistake 6: Animated GIFs for video
- Tools for image optimization
- How much speed will you gain?
- Quick checklist
If your website is slow, images are probably the biggest reason. On a typical content site they account for 50–70% of total page weight. Get image optimization right and you can shave seconds off your load time.
Here's how images hurt speed and the workflow to fix it.
How images hurt speed
1. They're huge
A single 4000-pixel hero photo straight from a camera can be 4–8MB. On a 4G connection (~1.6 Mbps) that's 20+ seconds of download. Even on fast Wi-Fi, multiple unoptimized images can push page weight past 10MB.
2. They block LCP
The Largest Contentful Paint is usually a hero image. A slow image → slow LCP → bad Core Web Vitals → bad SEO. See LCP: What It Means and How to Improve It.
3. They cause layout shifts
Images without width and height attributes push content around when they finally load. This kills your CLS score. See CLS: What It Means and How to Fix It.
4. They consume bandwidth on mobile
Most mobile users are on metered data. A 5MB page costs your visitor money — and they'll bail before it loads.
The image optimization workflow
Step 1: Use the right format
| Format | Best for | Size vs JPEG |
|---|---|---|
| AVIF | Photos, hero images | ~50% smaller |
| WebP | Photos, screenshots | ~30% smaller |
| JPEG | Photos (legacy fallback) | baseline |
| PNG | Transparency, screenshots with text | larger |
| SVG | Logos, icons, illustrations | tiny when scaled |
Modern browsers (95%+ of users in 2026) support WebP and AVIF. Use <picture> to provide fallbacks:
<picture>
<source srcset="/hero.avif" type="image/avif">
<source srcset="/hero.webp" type="image/webp">
<img src="/hero.jpg" alt="..." width="1200" height="600">
</picture>
Step 2: Resize to displayed dimensions
A 4000px image displayed at 800px wastes 80% of the bytes. Resize images to their actual display size, ideally generated at multiple sizes for responsive serving.
If you're on Next.js, the <Image> component does this automatically. WordPress can do it with plugins like Smush or via the srcset it generates from media library uploads.
Step 3: Serve responsive sizes
Use srcset and sizes to let the browser pick the right image for each device:
<img
src="/hero-800.webp"
srcset="
/hero-400.webp 400w,
/hero-800.webp 800w,
/hero-1600.webp 1600w
"
sizes="(max-width: 768px) 100vw, 800px"
width="800"
height="400"
alt="..."
>
The browser sees the viewport width, calculates which size to download, and never wastes bytes.
Step 4: Set explicit dimensions
Always include width and height attributes. Modern browsers use them to calculate aspect ratio and reserve space before the image arrives — eliminating CLS.
<!-- ❌ Causes CLS -->
<img src="/photo.jpg" alt="...">
<!-- ✅ No CLS -->
<img src="/photo.jpg" alt="..." width="800" height="450">
For responsive images, the width and height represent the intrinsic dimensions. CSS like max-width: 100%; height: auto; does the right thing in the browser.
Step 5: Lazy-load below the fold
Add loading="lazy" to images below the initial viewport:
<img loading="lazy" src="/photo.jpg" alt="..." width="800" height="450">
Critical: Do NOT lazy-load your hero image. Lazy loading delays the LCP image, which directly hurts your LCP score.
Step 6: Preload the LCP image
For the largest image visible on first load, do the opposite of lazy loading — preload it:
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high">
This can shave 500–1500ms off LCP on mobile.
Step 7: Use a CDN for image delivery
Image CDNs like Cloudflare Images, Cloudinary, imgix, and Vercel's Image Optimization handle on-the-fly resizing, format conversion, and edge caching. They turn one source image into infinite optimized variants.
If you're not using one, your images are probably 10–50% bigger than they need to be.
Common image mistakes
Mistake 1: Lazy-loading the LCP image
We covered this above. Don't do it.
Mistake 2: Using PNG for photos
PNGs of photos are 5–10× larger than the WebP equivalent. Use PNG only when you need transparency.
Mistake 3: Background images for hero content
CSS background-images can't be preloaded the same way as <img> tags, and browsers de-prioritize them. If your hero is a background image, switch to a real <img>.
Mistake 4: Serving the same image to everyone
A user on a 360px phone and a user on a 4K monitor shouldn't download the same image. Always use srcset.
Mistake 5: Not setting explicit dimensions
Causes CLS. Always set width and height.
Mistake 6: Animated GIFs for video
A GIF of a 5-second loop can be 10MB. The same content as MP4 or WebM is 500KB. Use <video autoplay loop muted playsinline> instead of GIFs.
Tools for image optimization
- Squoosh (squoosh.app) — free in-browser image compressor by Google. Convert to WebP/AVIF visually.
- ImageOptim (macOS) — drag-and-drop lossless compression
- TinyPNG — bulk PNG/JPEG compression
- Sharp (Node.js library) — for build-time optimization in custom pipelines
- Next.js
<Image>— handles everything automatically if you're on Next.js
How much speed will you gain?
A real example: a typical marketing page with 8 images.
- Before: 4.2MB total, LCP 4.8s, score 52
- After WebP + srcset + lazy loading + preload + width/height:
- After: 720KB total, LCP 1.4s, score 89
That's the difference between failing Core Web Vitals and passing them.
Quick checklist
Before publishing any page:
- All images converted to WebP (and AVIF where supported)
- All images resized to actual display dimensions
- All images have
widthandheightattributes - All below-the-fold images have
loading="lazy" - The LCP image is preloaded and has
fetchpriority="high" - All images have meaningful alt text
- Responsive sizes provided via
srcset
That's the entire workflow. Do it once, then bake it into your build process so you don't have to think about it again.
For the full speed optimization picture, see how to improve your PageSpeed Insights score or run a free audit to see where images are hurting your specific site.
Frequently Asked Questions
What's the best image format for the web in 2026?+
AVIF for photos when supported, WebP as the universal modern format, JPEG for legacy fallback. SVG for logos and icons. AVIF files are roughly 50% smaller than JPEG at the same quality.
Does lazy loading every image speed up my site?+
No — adding lazy loading to above-the-fold images (especially the LCP image) makes your site slower. Lazy loading is only for images below the initial viewport.
Should I serve different image sizes for different devices?+
Yes. Use srcset to let the browser pick the right size. A 360px-wide phone shouldn't download a 1600px-wide image meant for a desktop monitor.
See how your site really performs
Run a full website health check on mobile and desktop in 30 seconds — no signup needed.