Back to blog
Performance

Image optimization for web: AVIF, WebP and lazy loading

By Flávio Emanuel · · 6 min read

I discovered by accident that 70% of a website’s loading time came from images. Badly optimized images. Basically the client was paying for internet bandwidth they didn’t need.

Optimizing images sounds basic. But most devs don’t do it right. They use PNG for everything, leave resolution super high. Or compress too much and it gets pixelated.

Modern standards exist now. AVIF, WebP. Lazy loading. Srcset. It’s not complicated to implement. The impact is absurd.

JPEG is obsolete

Let me be direct: don’t use JPEG on a new site. It’s dead. Especially for image-heavy clinics.

JPEG is 20+ years old. Compression is okay but for modern photos, other formats are always better.

WebP is second place. Compatibility is basically universal now (all modern browsers support it since 2020). Size is 25-35% smaller than JPEG with similar quality.

AVIF is the new king. Compatibility is more recent (last 2 years) but it’s already solid. Size is 40-50% smaller than JPEG. The quality even when compressed is impressive.

Real example: patient smile photo at a clinic. 2.5MB in JPEG. Converted to AVIF. 600KB. Same resolution, same visual quality, to the human eye it’s identical.

How to implement: picture element

Not complicated. Use the <picture> tag:

<picture>
  <source srcset="smile.avif" type="image/avif">
  <source srcset="smile.webp" type="image/webp">
  <img src="smile.jpg" alt="before-after">
</picture>

Browser first tries to load AVIF. If not supported, tries WebP. If not supported, uses JPEG as fallback.

You offer the best format to each browser. User with a new browser? Gets compressed AVIF. User with an old browser? Gets JPEG which it supports.

Srcset and sizes: responsive images

This is where most people mess up. They serve the same huge image to mobile as to desktop. Massive waste.

Your site with a 1920x1080 image on mobile? Hit the screen, looks pixelated (because it resized via CSS) and wasted bandwidth.

Use srcset:

<picture>
  <source
    srcset="photo-small.avif 640w, photo-med.avif 1024w, photo-large.avif 1920w"
    type="image/avif">
  <img src="photo.jpg" alt="before" />
</picture>

You provide 3 versions of the same image in different sizes. Browser chooses which to download based on screen size. Mobile gets small (100KB). Desktop gets large (800KB).

For a clinic with a gallery of before-afters? The savings are colossal.

Lazy loading: load only what you see

Clinic page has 20 case photos. Do you really want to load all 20 right when the page opens? No.

Add loading="lazy" to the image:

<img src="photo.jpg" alt="case" loading="lazy">

Images load only when the user scrolls and gets near them. Your LCP (Largest Contentful Paint) drops dramatically.

Real: clinic page with 20 images above the fold, no lazy loading, took 4.5s for LCP. With lazy loading: 0.9s. Not even comparable.

Lazy loading is supported by all modern browsers. Automatic fallback in old browsers (loads everything anyway, but at least tried).

Tools: convert your images

Need to convert your images? Several options:

ImageMagick: command line, powerful, has a learning curve.

convert original.jpg -quality 80 output.avif

Squoosh (Google): website, visual, quick. squoosh.app

TinyJPG: pay a little but auto-optimizes.

I use a Node script that runs locally. Finds all JPGs in a folder, converts to AVIF and WebP, saves in subfolder. Runs in a minute.

If you prefer, build tools like sharp (Node) or imagemin automate everything.

A real case

Clinic client had 300+ case photos on the site. All JPEG, 2-3MB each. Site loaded in 8 seconds.

Converted everything to AVIF with srcset (3 sizes each). Implemented lazy loading. Added picture element with WebP fallback.

New site? 2.5 second LCP. Data bandwidth per page dropped from 8MB to 1.2MB.

Google Search Console started showing “Performance Improvement Detected” a few days later. Ranking went up because Core Web Vitals improved.

Client asked for more service searches (“why did it improve?”). Real result.

Extra tips

Always use alt text (matters for SEO and accessibility).

Compress your AVIF slightly less aggressively than WebP (AVIF looks ugly with very aggressive compression).

Test on your phone. Sometimes image gets pixelated at very low quality. Adjust the trade-off.

Put images on a CDN (Cloudflare, Vercel, anything). Delivery is 10x faster.

Monitor Core Web Vitals afterward. Google PageSpeed Insights shows exactly how much improved.

Is it worth it?

100% yes. Takes 2-3 hours to implement. Impact is permanent. Client saves on monthly bandwidth, site is faster, SEO improves.

If you’re optimizing a site and not looking at images, you’re leaving money on the table.

When NOT to use lazy loading

Here’s a detail: don’t use lazy loading on above-the-fold images.

That hero image showing on home when it loads? Load it directly. Lazy loading removes the benefit because the image gets slow. Your LCP stays bad.

Use lazy loading only on below-fold images. Those the user needs to scroll to see.

Important: the hero image can still be optimized. Use picture element with AVIF/WebP. Just don’t put loading=“lazy”.

Optimizing for mobile is priority

Know why 70% of traffic is mobile? Because phones have smaller screens and weaker connection.

Your responsive images need much smaller size for mobile. The srcset tag I showed:

<source srcset="photo-small.avif 640w, ..." type="image/avif">

Mobile gets the 640w version. 100KB max.

Without it? Desktop 1920w sending 800KB to a 375px screen. Criminal waste.

Smart compression

The compression quality you choose matters.

For photos (JPEG, AVIF, WebP): quality 75-85 is invisible to the human eye but saves 30% in size.

For images with text (PNG, which doesn’t compress): you need 90+ quality.

I test. Save same image at quality 70, 75, 80, 85. Open on phone. See which quality is invisible. Use that.

Cache and CDN

One thing nobody mentions: no point optimizing images if you don’t use a CDN.

Image served from your server in Brazil takes 400ms to reach user in São Paulo.

Same image on Cloudflare CDN? 50ms.

Always put images on a CDN. Cloudflare, Vercel, anything. Makes more difference than any format optimization.

My priority order:

  1. CDN (huge impact)
  2. Lazy loading below fold (big impact)
  3. AVIF + WebP (medium impact)
  4. Srcset responsive (medium impact)
  5. Quality adjustment (small impact)

Do this order and your site will be much faster.

Monitor results

After optimizing, use Google PageSpeed Insights.

Screenshot the report. Show client. “Your page improved from 45 to 87 on mobile”. Client is happy.

Core Web Vitals improving? Lighthouse green? Done, you optimized right.

  • Convert large images to AVIF and WebP
  • Implement picture element with fallbacks
  • Add lazy loading to all below-fold images
  • Create srcset with 2-3 sizes
  • Test on mobile and desktop
  • Put images on CDN (Cloudflare or similar)
  • Monitor Core Web Vitals after implementing

Read also: Why your website loads slowly | Core Web Vitals in 2026 | Lighthouse 100 doesn’t mean good site

Optimized images are money you take from the internet and put in your client’s pocket.

Next step

Need a dev who truly delivers?

Whether it's a one-time project, team reinforcement, or a long-term partnership. Let's talk.

Chat on WhatsApp

I reply within 2 hours during business hours.