Why your images are slowing your site down
Updated 12 October 2026 · 6 min read
Images are typically 50–70% of a page's transferred bytes. When a Core Web Vitals score is bad, images are the first place to look, and the cause is almost always one of three mistakes — none of which require a redesign to fix.
Mistake 1: serving far more pixels than the layout uses
A hero image that renders at 600 px wide on a phone does not need a 3000 px source. The browser downloads all of it and then throws 96% of the pixels away. This single mistake usually dwarfs any format choice: dropping 3000 px to 1200 px cuts bytes by roughly 85%, whereas switching that same image from JPEG to WebP cuts about 30%.
Fix: cap the source at 2× the largest width the layout actually uses, and use srcset so phones get the small file and desktop screens get the large one.
Mistake 2: the wrong format for the content
Two failure modes dominate. Photos exported as PNG, which is lossless and therefore enormous for photographic content. And UI screenshots pushed through aggressive lossy compression, which produces ringing around text and looks worse than a properly optimized PNG.
Fix: photos → WebP at 80–85%. Screenshots and flat illustrations → PNG, or WebP lossless if you want a smaller file. Icons → SVG. Anything that will never change → ship it pre-optimized rather than optimizing per request.
Mistake 3: missing width and height attributes
Without explicit dimensions the browser cannot reserve space, so the layout shifts when each image loads. That is Cumulative Layout Shift, and it is the cheapest of the three problems to fix — it is a two-attribute change, not a pipeline.
<img src="chart.webp" alt="Revenue by quarter"
width="1200" height="800" loading="lazy" decoding="async">
Combine with aspect-ratio in CSS and the image can be fully responsive while still reserving its box.
Checking your own site in five minutes
- Open your homepage in Chrome, then DevTools → Network → filter by Img and sort by Size. The top three offenders are your problem.
- For each one, compare its intrinsic pixel width (hover the file in DevTools) with the CSS width it renders at. Anything over 2× is wasteful.
- Check the format column. A photo served as PNG is an easy win.
- Run Lighthouse and look at the LCP element it names. Optimize that image specifically — a 300 KB image below the fold barely matters, while a 300 KB LCP image is fatal.
- Re-measure. If LCP did not move, the bottleneck is somewhere else, likely JavaScript.
Doing this automatically
Manual optimization decays the moment someone uploads a new image through a CMS. The durable version is a step in your pipeline:
- Static sites: run an optimizer over your image directory in CI, and fail the build if a page's image payload exceeds a byte budget you choose.
- User-generated content: optimize at upload, once, and store the derived sizes. Never optimize on every request if you can avoid it.
- Both cases: strip EXIF metadata. It can be tens of kilobytes of GPS coordinates and camera data that nobody needs, and it is also a privacy leak.
If you would rather not maintain that step yourself, that is precisely what our API is for — but the manual fixes above will get you most of the way for free.