Image Optimization Guide: WebP, AVIF, Lazy Loading, and Beyond
A technical image optimization guide — format selection, compression, responsive images, lazy loading, fetch priority, and the patterns that cut page weight in half.

Image optimization is usually the single biggest performance win available on any site. Most sites we audit are shipping images 5 to 20 times larger than necessary — costing 1 to 4 seconds of LCP and 30 to 70 percent of page weight that could be free.
This guide covers image optimization end to end. Format selection, compression, responsive images, lazy loading, fetch priority, CDN delivery, and the specific patterns that consistently move LCP and reduce page weight on real production sites.
The work is concrete. Most sites can cut total image weight 60 to 80 percent in a week of focused work, with proportional improvements to LCP and Core Web Vitals.
Why images dominate page weight
The average web page in 2026 is around 2 MB total. Images typically account for 50 to 70 percent of that weight.
This is not because images are inherently large. It is because most sites ship images:
- In old formats (JPEG, PNG) instead of modern (WebP, AVIF)
- At display sizes 3 to 10 times larger than rendered
- Without compression
- Loading eagerly when they should lazy-load
- Without proper responsive sizing
Each of these is a fix worth between 10 percent and 70 percent page weight reduction. Combined, they typically cut total weight 60 to 80 percent.
We covered the broader Core Web Vitals impact in our Core Web Vitals deep dive guide. Images are usually the biggest contributor to LCP issues.
Section 1 — Format selection
Picking the right format is the first decision, and the biggest single weight reduction.
Modern formats — AVIF and WebP
AVIF: 40 to 60 percent smaller than JPEG at equivalent quality. Best compression. Slowest to encode. Now supported in 95+ percent of browsers.
WebP: 25 to 35 percent smaller than JPEG at equivalent quality. Faster to encode. Supported in 97+ percent of browsers.
Recommendation: serve AVIF when supported, WebP as fallback, JPEG only for legacy browsers.
Modern hosting platforms (Vercel, Cloudflare Images, Imgix) handle the format negotiation automatically.
When to use JPEG vs PNG vs SVG
JPEG: photos, gradients, real-world images. Use for content with continuous tones.
PNG: graphics with sharp edges, transparency, logos with limited colors. PNG-8 is small. PNG-24 is large.
SVG: icons, logos, simple illustrations. Vector format, scales without quality loss, often the smallest format for icons.
For 2026, AVIF or WebP should be the default for photos. SVG for icons. PNG only when transparency is needed and SVG won't work.
GIF is dead
Animated GIFs should be replaced with MP4 or WebM video. The format is decades old and 5 to 10 times larger than modern alternatives.
For animated content, use <video autoplay loop muted playsinline> with WebM source. The file is smaller and the playback is smoother.
Section 2 — Compression
Compression is where most format gains come from. The format change without compression is half the win.
Quality settings
For WebP and AVIF photos:
- Quality 80-85: visually indistinguishable from the original in 90+ percent of cases
- Quality 70-75: slightly compressed but still good for most use
- Quality 60 and below: visible artifacts on photos, acceptable for thumbnails
Default to quality 80 to 85. Drop lower only if you need extreme compression.
Tools for compression
For one-off images: Squoosh.app (browser-based, free, supports all modern formats).
For batch compression: ImageOptim (macOS), Compressor.io, TinyPNG (paid but excellent).
For build pipelines: Sharp (Node), imagemin plugins for various build tools.
For hosted optimization: Cloudflare Polish, Vercel Image Optimization, Imgix, Cloudinary.
Lossless vs lossy
Lossless compression preserves every pixel exactly. Useful for logos and graphics where artifacts would be visible.
Lossy compression discards information. Acceptable for photos where the reduction is invisible at normal viewing.
Default to lossy for content images. Lossless for logos and graphics with sharp edges.
Section 3 — Responsive images
Serving the right size for the right viewport is one of the biggest wins.
The problem
A 4,000 x 2,000 image served to a mobile phone displaying it at 400 x 200 wastes 95+ percent of the downloaded data.
The solution — srcset and sizes
<img
src="hero-1200.webp"
srcset="
hero-400.webp 400w,
hero-800.webp 800w,
hero-1200.webp 1200w,
hero-2400.webp 2400w
"
sizes="(max-width: 768px) 100vw, 1200px"
alt="Hero"
width="1200"
height="630"
>
The browser picks the right size based on viewport and pixel density.
sizes syntax
sizes describes how the image is rendered, not its file dimensions. The browser uses it to pick the right srcset candidate.
Common patterns:
- Full-width hero:
sizes="100vw" - Half-width on desktop, full on mobile:
sizes="(max-width: 768px) 100vw, 50vw" - Fixed width:
sizes="800px"
Getting sizes right is critical. Wrong sizes means the browser downloads a larger image than needed.
Picture element for art direction
For different crops or compositions per breakpoint (not just different sizes), use <picture>:
<picture>
<source media="(max-width: 768px)" srcset="hero-mobile.webp">
<source media="(min-width: 769px)" srcset="hero-desktop.webp">
<img src="hero-desktop.jpg" alt="Hero">
</picture>
Useful when you want a different image composition (close-up vs wide shot) for mobile vs desktop.
Section 4 — Lazy loading
Don't load images that are not in the viewport.
Native lazy loading
<img src="below-fold.webp" loading="lazy" alt="...">
Supported in all modern browsers. Defers loading until the image approaches the viewport.
When to lazy-load
- Below-the-fold images (always)
- Long-scroll content (image galleries, product grids, blog content)
- Images in collapsed sections
When NOT to lazy-load
- The LCP image (load eagerly, with priority)
- Images visible above the fold on first paint
- Images that are immediately critical to the page experience
loading="eager" and the LCP
The LCP image should be loading="eager" (the default) and ideally have fetchpriority="high".
<img
src="hero.webp"
loading="eager"
fetchpriority="high"
alt="Hero"
width="1200"
height="630"
>
This is the single highest-leverage image optimization. Free LCP improvement of 200 to 800 ms in most cases.
Section 5 — fetchpriority for the LCP image
The fetchpriority="high" attribute tells the browser to fetch this resource ahead of others.
How it works
Without fetchpriority, browsers use heuristics to pick which resources to fetch first. The LCP image often loses to less-important resources.
With fetchpriority="high", the browser knows to prioritise this image. The result is dramatically faster LCP.
When to use it
- On the LCP image (and only the LCP image)
- For above-the-fold hero images that are likely the LCP
When NOT to use it
- On below-the-fold images
- On multiple images per page (defeats the purpose)
- On non-LCP images that happen to be important
The browser's prioritisation is "first among equals". Marking many things as high priority eliminates the signal.
Section 6 — Dimensions and aspect-ratio
Images without dimensions cause Cumulative Layout Shift. Always specify dimensions.
width and height attributes
<img src="hero.webp" width="1200" height="630" alt="...">
The browser uses these to reserve space immediately. When the image loads, no shift.
CSS aspect-ratio
.hero {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
For responsive images, aspect-ratio reserves space without committing to fixed dimensions.
Why this matters
A page with images missing dimensions can have a CLS score of 0.3 to 1.0. Adding dimensions to every image typically drops CLS to 0.05 or below.
We covered the CLS mechanics in our Core Web Vitals deep dive guide.
Section 7 — Background images
CSS background images are easy to misuse for performance.
The hidden cost of background images
A background image loaded via background-image: url(...) is treated like any other image by the browser — fetched, parsed, painted. But it lacks the optimization features available to <img>:
- No native lazy loading
- No
fetchpriorityhint - No
srcsetfor responsive sizing - No automatic format negotiation (unless your CDN provides it)
When to use <img> over background image
For any content image (hero, product, illustration), prefer <img> over background-image. The optimization features are too valuable to forgo.
When background images make sense
- Decorative backgrounds that are not content
- CSS gradients (always background, never img)
- Repeating textures or patterns
- Images that need to be behind other content with overlap
For these cases, the lack of optimization features is acceptable.
Section 8 — CDN delivery
A CDN serves images closer to the user, reducing latency.
Built-in optimization CDNs
Modern image CDNs handle most optimization automatically:
- Cloudflare Images: format conversion, resizing, compression
- Vercel Image Optimization: handled automatically with
next/image - Cloudinary: most comprehensive, expensive at scale
- Imgix: powerful, mid-priced
- Bunny Images: cheaper alternative
For most SMEs, Cloudflare Images or Vercel handles this without per-image effort.
Origin shielding
CDNs cache images at edge locations. For images that are not yet cached at a specific edge, the CDN fetches from your origin.
A "shield" layer between the edge and origin reduces origin requests dramatically — useful for sites with many edge locations and a single origin server.
HTTP/2 and HTTP/3
Modern protocols multiplex multiple image requests over a single connection. This eliminates the "6 concurrent connections per origin" limit that hurt HTTP/1.1 sites.
Most modern CDNs serve HTTP/2 or HTTP/3 by default. Verify with curl -I --http2 https://your-cdn.com/image.webp.
Section 9 — Image-heavy pages — gallery and product grids
Some pages have dozens of images. Optimization patterns specific to these.
Pagination over infinite scroll for SEO-critical pages
Infinite scroll loads more images as users scroll. SEO-wise, search engines often fail to crawl beyond the initial set.
For product catalog and gallery pages, paginate at 24 to 48 images per page. SEO-friendly, lower initial weight, fast load.
Use Intersection Observer for advanced lazy loading
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
observer.unobserve(img);
}
});
});
For custom lazy-loading behaviour beyond loading="lazy", Intersection Observer gives you control.
Pre-load adjacent images
For galleries and carousels, pre-load the next and previous images so the transition feels instant.
<link rel="prefetch" href="next-image.webp">
A 14-day image optimization plan
If your site has unoptimised images, follow this sequence.
Days 1 to 3 — Audit. List every image on your top 10 pages. Note format, size, dimensions, lazy-loading status.
Days 4 to 6 — Format conversion. Convert all photos to WebP at quality 80-85. Use Squoosh or batch tool.
Days 7 to 9 — Sizing. Generate appropriate responsive sizes. Update srcset and sizes attributes.
Days 10 to 11 — Lazy loading. Add loading="lazy" to below-fold images. Add loading="eager" and fetchpriority="high" to LCP image.
Days 12 to 13 — Dimensions. Add width and height to every image. Set up aspect-ratio in CSS for responsive containers.
Day 14 — Measure. Re-run Lighthouse. Compare LCP, CLS, and total page weight to baseline.
Most sites see 50 to 80 percent total image weight reduction in this window, with LCP improvements of 1 to 3 seconds.
A real example — Marseille cosmetics image audit
We audited a Marseille cosmetics e-commerce site shipping 4.7 MB of images on the homepage. Format breakdown: JPEG and PNG only, no responsive sizes, no lazy loading, no dimensions specified.
After 10 days — WebP conversion, responsive sizes via srcset, lazy loading on below-fold images, fetchpriority="high" on hero, dimensions added everywhere — total image weight dropped to 680 KB. LCP improved from 4.2 seconds to 1.6 seconds. Conversion rate lifted 31 percent in the following 60 days. The full story is in our Marseille cosmetics case study.
Common image optimization mistakes
These are the patterns we see most often.
JPEG when WebP would work. Free 25 to 35 percent reduction. Almost universally skipped on older sites.
Single image size for all viewports. Mobile downloads desktop-sized images. Use responsive srcset.
Wrong sizes value. Causes browser to pick the wrong candidate from srcset.
Missing dimensions. Causes CLS spikes. Always specify width and height.
Lazy-loading the LCP image. Defers the most important image. Mark as eager and high priority.
Stock photo hero at 4 MB. Compress and resize before upload, not after.
Background images for content. Loses native optimization features. Use <img> for content images.
No CDN. Origin-served images are slower for geographically-distant users.
Frequently asked questions
Should I use AVIF or WebP?
Both. Serve AVIF when supported, WebP as fallback, JPEG only for legacy browsers. Modern image CDNs handle this automatically.
What quality setting for WebP?
80 to 85 is the sweet spot for photos. Visually indistinguishable from the original in most cases, with significant file size reduction.
How many responsive sizes should I generate?
Typically 3 to 5 widths spanning your common viewport sizes. For most sites: 400, 800, 1200, 2400 widths.
Is lazy loading still beneficial in 2026?
Yes. Native lazy loading is in every modern browser. Free LCP improvement for below-fold images.
Should I use next/image or custom image components?
For Next.js apps, next/image is the default and handles most optimization automatically. We covered the specifics in our Next.js performance best practices guide.
Do I need a paid image CDN?
For small sites, no. Vercel or Cloudflare's free tiers cover the essentials. For high-traffic sites or sites with many images, paid CDNs (Imgix, Cloudinary) deliver better optimization at scale.
Get an image optimization audit
We audit site images free of charge. Within 48 hours we deliver a per-image breakdown of waste and a prioritised optimization plan.
Book a free 30-minute audit. We screen-share, walk through your image footprint, and you leave with a clear action plan.
Or explore our Web Development service for the full system we run on performance-focused client accounts.
Want these strategies applied to your business?
30 minutes of free audit with concrete recommendations tailored to your business.
Read next
The Lighthouse Audit Checklist: 50 Points We Check on Every Site
A comprehensive Lighthouse audit checklist — performance, accessibility, best practices, SEO. The 50-point list we run on every web performance engagement.
Third-Party Script Management: How to Stop Tags From Killing Your Site
A guide to managing third-party scripts — Google Tag Manager, chat widgets, analytics, marketing pixels. Strategies for deferring, replacing, and removing scripts.
Web Fonts Performance: Subsetting, font-display, and Preloading
A technical guide to web fonts performance — formats, subsetting, font-display, preloading, variable fonts, and the patterns that eliminate FOIT and FOUT.