WordPress Image Optimisation: WebP, Sizes and Lazy Loading
How WordPress handles images, which registered sizes actually matter, when WebP and AVIF are worth it, and the lazy-loading default that hurts your LCP.

On most WordPress sites, images account for more bytes than everything else combined. They're also the part of a page most likely to have been uploaded straight from a phone or a stock library at full resolution, because nothing in the upload flow stops you.
Here's how WordPress actually handles images, and the changes that move the needle — roughly in order of effect.
What WordPress does when you upload an image
WordPress keeps your original and generates a set of resized copies: thumbnail, medium, medium_large, large, and whatever additional sizes your theme and plugins have registered. A single upload can easily produce eight or more files.
It then builds a srcset attribute when the image is output, listing those sizes with their widths so the browser can pick an appropriate one. This is genuinely good default behaviour — it's why a WordPress site often serves reasonable images without anyone configuring anything.
Where it goes wrong is when the registered sizes don't match how images are actually displayed, or when a template outputs the full-size original because that was the easiest thing to write.
Register sizes that match your design
Look at the largest space each image occupies in your layout, on a 2x screen. A card image displayed at 400px wide needs an 800px file, not a 2000px one. Register a size for it, and use that size in the template.
Be disciplined about how many sizes you register. Every registered size is another file generated on every upload, which costs disk space and makes bulk imports slow. Four or five well-chosen sizes beat a dozen speculative ones.
If you change or add sizes on an existing site, remember that existing uploads won't have them until they're regenerated. Until then, WordPress falls back to whatever it has — often the full-size original.
The lazy-loading trap
Since WordPress 5.5, images get loading="lazy" automatically. For images further down the page this is exactly right — the browser doesn't fetch what nobody has scrolled to.
For the image at the top of the page it is actively harmful. The hero image is usually the Largest Contentful Paint element, and lazy-loading tells the browser to deprioritise fetching it until layout says it's needed. You have made the specific thing Google measures slower.
WordPress has some built-in logic to skip the first image on a page, but it's imperfect, and it doesn't know about images your theme outputs outside the content. Check what your hero actually renders with, and force loading="eager" with fetchpriority="high" on it.
Always set width and height
Every img element should carry width and height attributes, or an aspect-ratio in CSS. Without them the browser doesn't know how much space to reserve, so the page reflows when each image arrives — which is exactly what Cumulative Layout Shift measures.
WordPress adds these automatically for images in post content. It doesn't for images your theme outputs directly, which is where most of the problem lives. If you write an img tag in a template, write its dimensions too.
Modern formats: WebP and AVIF
WebP typically cuts file size substantially against JPEG at similar visual quality, and it's supported everywhere that matters now. AVIF goes further again, with slightly less universal support and slower encoding.
WordPress supports WebP uploads natively and recent versions can generate WebP copies of uploaded JPEGs. Plugins and CDN image services can do the same automatically, often with a fallback for browsers that need it.
One caveat worth knowing: converting an already-compressed JPEG to WebP gives a smaller gain than converting from the original. And a badly resized WebP is still worse than a correctly sized JPEG — format is the second-order optimisation, size is the first.
Compression that doesn't look compressed
- For photographs, quality around 75-85 is usually indistinguishable from the original at a fraction of the size. Below 70 you start seeing artefacts in gradients and skies.
- Strip EXIF metadata on upload. Camera data and GPS coordinates add weight and, for photos taken on a phone, sometimes leak a location you didn't mean to publish.
- Screenshots and graphics with flat colour and text compress far better as PNG or WebP than as JPEG, which makes text edges fuzzy.
- Use SVG for logos, icons and simple illustrations — it's tiny and sharp at any size. Sanitise uploaded SVGs, because they can contain script.
Where to do the work
There are three places image optimisation can happen, and they have different trade-offs. Doing it before upload gives you the most control and no runtime cost, but relies on whoever is publishing to remember. A plugin that optimises on upload is the pragmatic middle: it catches everything and needs no discipline, at the cost of some server work. A CDN image service transforms on request, which handles legacy uploads too and moves the work off your server entirely.
For a site with multiple editors, automatic optimisation on upload or at the CDN is the only thing that reliably holds. Guidelines in a document do not survive contact with a deadline.
Backgrounds and CSS images
Images set as CSS backgrounds sidestep everything above: no srcset, no lazy loading, no width and height, and the browser only discovers them after it has parsed the stylesheet. That late discovery is a real cost when the background is the hero.
Use an actual img element for anything that's content, and reserve CSS backgrounds for decoration. If a background image is unavoidable above the fold, preload it so the browser doesn't wait for the CSS to find out about it.
Alt text, briefly
Alt text isn't a performance matter, but it belongs in the same habit. Describe what the image shows and why it's there, in a sentence. Leave it empty for purely decorative images so screen readers skip them rather than announcing a filename.
Don't stuff keywords into it. It's read aloud to people, and it's one of the clearer signals to a search engine that a page is trying too hard.
A quick audit
- Open the network panel, filter to images, and sort by size. Anything over a few hundred kilobytes on a normal page needs explaining.
- Check the LCP element in PageSpeed Insights and confirm it isn't lazy-loaded.
- View source on a template-rendered image and check for srcset, width and height.
- Look at the uploads directory size; if it's enormous relative to the content, originals are probably being served somewhere.
- Test on a phone, where the difference between a 200KB and a 2MB hero is the difference between a usable site and a bounce.
Frequently asked questions
Should I convert all my images to WebP?
For photographs, yes — it's a meaningful size reduction with no visible quality loss and support is universal now. Keep SVG for logos and icons, where it's better than any raster format. The larger win, though, is serving correctly sized images; format comes second.
Why is my hero image hurting my LCP score when it's already compressed?
Most likely it's being lazy-loaded. WordPress adds loading="lazy" to images by default, and on the hero that tells the browser to defer fetching the exact element being measured. Set loading="eager" and fetchpriority="high" on it, and preload it if it's a CSS background.
Do I need an image optimisation plugin?
If more than one person uploads images, yes — automatic optimisation is the only thing that survives a deadline. If you're the only publisher and you're disciplined about resizing before upload, you can skip it. A CDN that transforms images on request achieves the same thing without server-side work.
How do I fix images that were uploaded at full size?
Regenerate thumbnails so the registered sizes exist for those uploads, then make sure your templates request a named size rather than 'full'. An optimisation plugin or image CDN can also compress the existing library in bulk. Check the templates first — regenerating won't help if the code still asks for the original.
How many image sizes should I register?
Four or five that match actual display sizes in your design, at 2x for high-density screens. Every extra registered size is another file generated on every upload, which slows bulk imports and eats disk. Speculative sizes 'just in case' are the common mistake.
Topics
- WordPress image optimization
- WebP WordPress
- compress images WordPress
- WordPress image sizes