How to fix oversized and outdated images
What the next-gen formats audit actually asks for, and how to fix it with WebP or AVIF, correct sizing and srcset — plus why lazy-loading your hero image backfires.
What the audit is actually complaining about
“Serve images in next-gen formats” means your images are encoded as JPEG, PNG or GIF where WebP or AVIF would carry the same picture in fewer bytes. “Properly size images” means you are sending more pixels than the layout displays. They are the same underlying problem — shipping weight the visitor never sees a benefit from — and the fix order matters: size first, then format. A 4000-pixel camera photo displayed at 800 pixels wastes more bytes through size than any format can claw back.
Step 1 — find out if images are actually your problem
Fix the thing that costs the most first. Run your page through the checker — if the biggest win is a script or the server, do that guide instead. If it is images, the LCP timeline on your result tells you where the time sits: image fixes only shorten the download phase.
To find which element is the LCP element: DevTools → Performance → run a recording → click the “LCP” marker, or simpler, run Lighthouse in DevTools and open the “Largest Contentful Paint element” audit. It names the exact node. That is the one image whose treatment matters most.
Step 2 — resize to what the layout displays
Export each image at the largest size it is ever displayed, times two for high-density screens. A hero shown at 800×450 needs a 1600×900 source, not the 6000×3375 original. Any image editor does this; so does every build pipeline:
# sharp (Node) — resize and convert in one pass
npx sharp-cli resize 1600 --input hero.jpg --output hero.webp
# or plain ImageMagick
magick hero.jpg -resize 1600x -quality 80 hero.webpStep 3 — serve WebP, with AVIF where it's worth it
WebP is supported by every current browser and is the sensible default. AVIF is smaller still but slower to encode — worth it for the handful of large images that dominate your weight, unnecessary for icons. The <picture> element serves the best format each browser understands:
<picture>
<source srcset="/img/hero.avif" type="image/avif" />
<source srcset="/img/hero.webp" type="image/webp" />
<img src="/img/hero.jpg" width="1600" height="900" alt="…" />
</picture>Keep the width and height attributes — they reserve space and prevent layout shift.
Step 4 — send small screens small files with srcset
A phone at 375 CSS pixels does not need your 1600-pixel hero. srcset lists the sizes you have; sizes tells the browser how wide the image renders so it can pick:
<img
src="/img/hero-800.webp"
srcset="/img/hero-400.webp 400w,
/img/hero-800.webp 800w,
/img/hero-1600.webp 1600w"
sizes="(max-width: 640px) 100vw, 800px"
width="800" height="450" alt="…" />Step 5 — treat the LCP image as the exception
Everything below the fold should lazy-load. The LCP image is the opposite case: the page is judged by how fast it appears, so tell the browser to fetch it first and never let a plugin lazy-load it:
<img src="/img/hero-800.webp" fetchpriority="high"
width="800" height="450" alt="…" />loading="lazy" on the hero is the classic own goal: it moves the one image the visitor is waiting for to the back of the queue. Optimisation plugins that blanket-lazy-load “all images” cause exactly this — every serious one has an “exclude the first N images” setting; set it to 1 or 2.
How to verify
Re-run the check. The image opportunity should shrink or disappear, and if the LCP element is an image, the timeline’s download phase should visibly drop. In DevTools → Network → Img you can confirm the served format and transfer size per image — the “Type” column should say webp or avif, and the hero should be one of the first requests, not the last.
If you'd rather not run a pipeline
Everything above is free and permanent: export at display size, convert with sharp or ImageMagick, write the markup once.
Common questions
- Should I use WebP or AVIF?
- WebP is the safe default: every current browser supports it, encoders are everywhere, and it typically cuts a JPEG's weight by 25–40% at the same visible quality. AVIF compresses harder — often another 20–30% smaller than WebP — but encoding is slower and very old browsers skip it. The picture element lets you serve AVIF with a WebP or JPEG fallback, so you never have to choose one for everyone.
- Is 'Serve images in next-gen formats' the same problem as 'Properly size images'?
- They are two symptoms of the same mistake: shipping more pixels than the page displays. Format converts each pixel more efficiently; sizing sends fewer pixels in the first place. Sizing usually saves more, which is why resizing a 4000px camera photo down to its display size routinely beats any format change — do both, sizing first.
- Do converted images look worse?
- Not at sensible settings. WebP at quality 80 and AVIF at quality 50–60 are visually indistinguishable from a high-quality JPEG for photographic content on real screens. If you can see the difference in an A/B at normal zoom, raise the quality a notch — you will still be far smaller than the original.
- Will fixing images fix my LCP?
- Only if the LCP element is an image, and only for the download part of its time. If the image is discovered late or render is blocked by CSS, a smaller file changes little — run the check and read the timeline it shows you: the phase the time actually sits in tells you whether this guide is the right one.
- Should I lazy-load all my images?
- All except the ones visible before scrolling — above all, never the hero. loading="lazy" on the LCP image tells the browser to deprioritise the exact thing the visitor is waiting for, and it is one of the most common self-inflicted LCP problems we see.
Check a page against this
Enter any public URL. You’ll get the one change that recovers the most load time, what it’s worth, and the measurements underneath.
Other guides
- How to fix a slow LCP — Your main image or headline takes too long to appear.
- How to fix layout shift — Content jumps around while the page loads.
- How to fix slow INP — Taps and clicks take a moment to do anything.
- How to fix a slow server response — Your server is slow to start replying at all.
- How to eliminate render-blocking CSS and JS — CSS and JS files stop anything appearing on screen.
- Why you're seeing "no field data" — Google has no real-visitor data for your site yet.
- How to cut unused JavaScript — You ship JavaScript this page never runs.
- How to fix your cache headers — Returning visitors re-download files they already have.
- Why your score is different on every run — The score is different every time you test.
- Fast on desktop, slow on mobile — Desktop looks fine; the phone test says otherwise.
- Why Search Console still shows the old numbers — You fixed it weeks ago and Search Console hasn't noticed.