# WordPress AVIF and WebP image delivery

Serve AVIF and WebP from WordPress with srcset, sizes and nginx cache. What actually moves LCP.

- Date: 2026-08-12
- Category: WordPress

WordPress AVIF WebP delivery is the image work I do before I blame the theme for a slow LCP on a catalogue page. I am Alan Vo, a Gold Coast web developer with 18 years on business sites and shops. In 2026 WordPress can generate and serve modern formats, but "the plugin is on" is not the same as a hero that is the right width, in AVIF or WebP, with `srcset`, `sizes`, and a cache that does not fight the format.

This note is for WooCommerce and editorial WordPress sites where the LCP element is almost always an image. Furniture, prints, and photography shops live or die on that file. If you also care about hosting, read [hosting, cache and CDN for WordPress stores](https://alanvo.com/blog/hosting-cache-cdn-wordpress/) after this, because a perfect `srcset` still loses to a cold origin.

## Why WordPress AVIF WebP work still moves LCP

WordPress AVIF WebP work still moves LCP because the largest contentful paint on a PLP or PDP is usually the product or hero image, not the logo. Compressing a 2400px JPEG to 400KB and calling it done still ships the wrong format and often the wrong size. AVIF and WebP cut bytes for the same visual. `srcset` and `sizes` stop a phone from downloading the desktop master. `fetchpriority="high"` on the LCP image tells the browser to start that request earlier.

WordPress has supported WebP in the media library for years and added AVIF support in 6.5 for environments where the host can encode it. That last clause is the production catch. Shared hosts without the right image library will silently skip AVIF. You upload a JPEG, you expect an AVIF sibling, you get only JPEG and WebP, or only JPEG. I check the uploads directory, not the plugin settings screen.

The [WordPress performance optimisation handbook](https://developer.wordpress.org/advanced-administration/performance/optimization/) covers media and related front-end costs at a platform level. I treat it as the baseline: do not concatenate a random "smush everything" plugin on top of core sub-sizes without knowing which sizes you actually print.

I do not invent conversion percentages for this work. Byte reduction is the claim I will stand on. If a store already publishes a conversion number on a work case, that number stays there. Image format is usually a Core Web Vitals job.

## How WordPress AVIF WebP delivery actually works

WordPress AVIF WebP delivery actually works as extra files in the media library plus markup that points at them. On upload, WordPress (or a helper plugin, or a CDN transform) creates sub-sizes. If AVIF and WebP generation is enabled and the server can encode, you get additional files per size. Front-end markup should use `img` with `srcset` listing those candidates, `sizes` describing the layout, and `type` only if you use `picture` with explicit sources.

![WordPress AVIF WebP in the block editor on a laptop](../../images/blog/wordpress-avif-webp-images-1.jpg)

There are three common delivery patterns:

1. Core sub-sizes only. WordPress prints `srcset` for JPEG/WebP/AVIF depending on what exists and what `wp_get_attachment_image` is asked to do. This is the path I want on custom themes.
2. Plugin replacement. A plugin rewrites every `img` through a CDN or local converter. Fine if it preserves dimensions and does not strip `width`/`height`. Bad if it wraps everything in JavaScript lazy loaders that delay the LCP image.
3. nginx or CDN format negotiation. The URL stays `.jpg` and the cache varies on `Accept`. This can work well, and it can also cache the wrong format for the next user if Vary is wrong.

I prefer real distinct URLs for AVIF and WebP when I control the theme. Negotiation is extra ops. Negotiation is also how you get a WebP file served with a JPEG content-type and a confused CDN.

`sizes` is the part teams skip. A `srcset` with 300w, 768w, 1024w, 1536w is useless if `sizes` says `100vw` on a product image that is 40% of a desktop viewport. The browser then picks a file that is too large. I write `sizes` from the actual CSS layout: gallery column, card width, hero full-bleed with max-width.

Lazy loading is correct for below-the-fold cards and wrong for the LCP image. Native `loading="lazy"` on the hero is a classic own-goal. WordPress core tries to skip lazy load on the first image in some loops. Builder widgets and custom loops often put it back. I inspect the live hero tag, not the plugin's "apply lazy load to all images" checkbox.

## WordPress AVIF WebP production checklist

WordPress AVIF WebP production is a checklist you run on staging with a real product photo, not a tiny logo.

1. Confirm the host can encode AVIF and WebP. Upload a test JPEG, look in `uploads` for extra files, or use the media details screen.
2. Keep original uploads sane. Photographers send 6000px TIFFs. Set a max upload dimension or a pre-process step so you are not generating twenty derivatives of a 40MB file.
3. Register only the image sizes the theme uses. Dead sizes still cost disk and CPU on upload.
4. Use `wp_get_attachment_image()` (or Woo gallery helpers that go through it) so `srcset` and `sizes` are not hand-typed wrong on one template and missing on another.
5. Set `width` and `height` on every content image to limit CLS. Art-direction crops still need the displayed box.
6. Mark the LCP image: no lazy load, `fetchpriority="high"` on that node only, preconnect only if the image is on another origin.
7. Do not lazy-load background images and then wonder why LCP is a painted CSS background. Convert LCP visuals to `img`.
8. Configure nginx or the CDN to cache AVIF and WebP by URL or by a correct `Vary: Accept` if you negotiate. I have a small nginx snippet in this repo for AVIF cache headers when we own the vhost.
9. Strip plugin JS lazy loaders from the hero. Native lazy on non-LCP images is enough for most shops.
10. Check retina: `srcset` should include a 2x candidate when the layout is fixed width, without sending 3x to every phone.
11. Verify WooCommerce gallery thumbnails are not requesting the full hero file.
12. Re-generate thumbnails after changing sizes, then purge CDN. Old URLs will otherwise 200 with stale JPEGs.

![Developer desk with two monitors during WordPress AVIF WebP work](../../images/blog/wordpress-avif-webp-images-2.jpg)

Print shops and photography archives need a second pass: zoom viewers often request a huge asset on first click. That click is INP and network. Serve a large WebP/AVIF for zoom, not the unprocessed original camera file.

## What breaks with WordPress AVIF WebP

WordPress AVIF WebP breaks when the HTML still points at a JPEG master, when the CDN caches one format for all users, or when a plugin replaces `img` with a placeholder that swaps late.

Specific failures I still see:

- Safari or older Android getting an AVIF it cannot decode because the `picture` fallback order is wrong. Always keep a JPEG or WebP fallback the browser can paint.
- Plugins that serve AVIF to all User-Agents from a single URL without Vary, then a cached AVIF hits a browser that wanted JPEG.
- Double compression: JPEG saved at 60, then AVIF from that JPEG, then a CDN quality slider. You get muddy fabric and wood grain. Start from a high-quality original, encode once.
- Colour profile surprises. Some AVIF pipelines shift product colour. Merchants notice before Lighthouse does. Compare a calibrated JPEG and AVIF on a real monitor for hero SKUs.
- `image/avif` 404s after a migrate because only JPEGs were copied. Regenerating sizes is part of go-live.
- Page builders that print a dummy 1px GIF or SVG blur-up and load the real image in JS. LCP becomes the dummy or a late swap.
- `srcset` with `w` descriptors that do not match actual file widths after a crop plugin ran.

![Website wireframes on paper next to a keyboard](../../images/blog/wordpress-avif-webp-images-3.jpg)

Email and PDFs are out of scope. I do not convert invoice attachments to AVIF. This is a storefront and editorial problem.

## How to measure image format work

Measure the LCP resource, not "images" as a bucket. In CrUX, watch LCP for PLP and PDP. In the lab, log the LCP element's URL, content-type, transfer size, and whether it was render-delaying.

I record:

- Transfer size of the LCP file before and after AVIF/WebP.
- Whether the LCP URL is in the initial HTML (good) or injected (bad).
- `sizes` accuracy: DevTools "used" vs "candidate" in the image tooltip.
- Decode time on a mid phone, because a tiny AVIF that is still 3000px wide can cost main thread.

Pair this with the broader [image formats and LCP](https://alanvo.com/blog/image-formats-improve-lcp/) notes when the stack is not WordPress-specific. The catalogue rule is the same: hero is LCP, format and width are the first levers.

Do not declare victory from a desktop Lighthouse 100 if mobile field LCP is still the uncached original JPEG. Field data lags. I keep the lab URL as a regression test in the release notes.

## Related work on this site

Image-led WooCommerce is the proving ground. The [Skanvi furniture storefront](https://alanvo.com/work/skanvi/) depends on product photography and story; a heavy JPEG hero would sit on every PDP. [Ross Halfin Photography](https://alanvo.com/work/ross-halfin-photography/) is an archive and print shop where the media library is the product. Both were contract development on an agency team. Format, `srcset`, and cache headers are part of making those pages feel like the print quality the brand already paid for, without shipping camera originals to a phone.

## FAQ

### Does WordPress AVIF WebP replace the need for `srcset`?

WordPress AVIF WebP does not replace `srcset`. A correctly encoded AVIF that is still 2400px wide is the wrong file for a 360px card. Format cuts bytes per pixel. `srcset` and `sizes` pick the pixel count. You need both.

### Should WordPress AVIF WebP be done in a plugin or in nginx?

WordPress AVIF WebP can be generated in WordPress and cached by nginx or a CDN, or transformed at the edge. I generate in WordPress when I want predictable URLs and media-library previews. I use edge transforms when the host cannot encode AVIF and the CDN contract is clear about caching and fallbacks. I do not do both on the same image URL.

![Content editor reviewing a page on a tablet](../../images/blog/wordpress-avif-webp-images-4.jpg)

### Is WordPress AVIF WebP enough to pass Core Web Vitals?

WordPress AVIF WebP is often enough to move LCP when the hero was the problem. It will not fix INP from a tag manager, nor TTFB from an uncached PHP origin. Treat images as one layer. Hosting and JS are separate tickets.

### Can I turn on WordPress AVIF WebP on a live shop without regenerating?

You can turn on WordPress AVIF WebP for new uploads and leave old files as JPEG. LCP URLs that still use old files will not change. Plan a regenerate and CDN purge for the templates that matter, then spot-check colour on hero SKUs before you call it done.



HTML version: https://alanvo.com/blog/wordpress-avif-webp-images/
