Images are usually the largest part of a WordPress page payload. Optimising them improves Core Web Vitals (especially LCP), reduces bandwidth costs, increases cache efficiency, and delivers a better mobile experience — all without changing the design.
1. Audit current image bloat
Find large uploads
# Find images over 2 MB
find wp-content/uploads -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -size +2M -exec ls -lh {} \; | sort -k5 -h -r | head -20
# Find images over 500 KB
find wp-content/uploads -type f \( -iname "*.jpg" -o -iname "*.jpeg" -o -iname "*.png" \) -size +500k | wc -l
Check total uploads size
du -sh wp-content/uploads
Check specific year/month directories
du -sh wp-content/uploads/202* | sort -h
This helps you find which years are driving the bulk of storage costs.
Quick WordPress report
wp db query "SELECT COUNT(*) as total, ROUND(SUM(post_content_length)/1024/1024, 2) as content_mb FROM (SELECT LENGTH(post_content) as post_content_length FROM wp_posts WHERE post_type='attachment' AND post_mime_type LIKE 'image/%') t"
2. Source image dimensions
The most impactful optimisation is resizing source images before upload. Common mistakes:
- Uploading 6000×4000 px DSLR photos for a hero image displayed at 1400 px
- Using full-resolution PNGs for logos that should be SVG or small WebP
- Not cropping to the actual display aspect ratio
Check for oversized images
Open Chrome DevTools → Network tab → filter by Img. Sort by size descending. Any image that is 3+ MB but displays at under 500 px wide in the layout is a prime target.
Recommended maximum dimensions
| Use case | Max width | Format |
|---|---|---|
| Full-width hero | 2000–2500 px | WebP or progressive JPEG |
| Content images | 1500 px | WebP or JPEG |
| Thumbnails / grid | 600 px | WebP |
| Logos | SVG or 200 px PNG/WebP | SVG preferred |
| Product images (WooCommerce) | 1200 px main, 600 px thumbnail | WebP |
3. Format selection
WebP (recommended default)
- 25–35% smaller than equivalent JPEG
- Supports transparency (replaces PNG for most cases)
- Supported by all modern browsers
- WordPress 5.8+ has built-in WebP support
AVIF (when you can handle the tradeoffs)
- Up to 50% smaller than JPEG
- Slower encoding — can timeout on large images on small VPS
- Browser support is good but not universal (Safari added in 16.x)
- Best used via CDN or build-time processing
JPEG (fallback)
- Still necessary for broadest compatibility
- Use progressive JPEGs for perceived performance
PNG
- Only use when transparency is required without WebP
- For logos and icons, SVG is better than PNG
4. Compression targets
Rough targets for business sites (not photography portfolios):
| Image type | Target size |
|---|---|
| Full-width hero | Under 250 KB |
| Inline content images | Under 150 KB |
| Thumbnails | Under 60 KB |
| Product images (WooCommerce main) | Under 200 KB |
| Logos and icons | Under 20 KB (SVG preferred) |
| Background patterns/textures | Under 100 KB |
Photography and design portfolio sites may need higher quality. For 90% of business WordPress sites, these targets are achievable without visible degradation.
5. Lazy loading strategy
WordPress 5.5+ adds native loading="lazy" to images. This is good, but needs tuning:
The LCP image must NOT be lazy-loaded
The Largest Contentful Paint element (usually the hero image) must load immediately. If your theme lazy-loads everything, exclude the hero.
Check which image is LCP:
- Open Chrome DevTools → Lighthouse → Generate report
- Look at “Largest Contentful Paint element” in the Diagnostics section
- If it is an image with
loading="lazy", fix it
CSS background images
loading="lazy" does not apply to CSS background images. If your theme uses CSS backgrounds for hero sections, either:
- Inline the critical background image in the HTML
- Use
<img>withobject-fitinstead - Accept the LCP tradeoff
6. CDN delivery for images
CDN-based image optimisation is often cleaner than running heavy image processing on a small VPS.
When to use a CDN for images
- Images are a major bandwidth cost
- Audience is geographically spread
- Editors upload inconsistent image sizes
- You need automatic WebP/AVIF conversion
- You want on-the-fly resizing without generating intermediate files
CDN image features comparison
| Service | On-the-fly resize | WebP auto | AVIF support | Pricing |
|---|---|---|---|---|
| Cloudflare Polish/Images | Yes (paid plans) | Yes | Yes | Free tier limited |
| Bunny Optimizer | Yes | Yes | Yes | Usage-based |
| ImageKit | Yes | Yes | Yes | Free tier available |
| Cloudinary | Yes | Yes | Yes | Free tier generous |
| imgix | Yes | Yes | Yes | Usage-based, higher cost |
Setting up Bunny CDN for images
- Create a pull zone pointing to your WordPress site
- Enable Bunny Optimizer
- Configure automatic WebP delivery
- Update WordPress to use the CDN URL (via plugin or filters)
7. Avoid optimisation plugin pile-ups
A common mistake is running multiple tools simultaneously:
- A local plugin converts to WebP
- A CDN also converts to WebP
- Another plugin adds lazy loading
- The theme also adds lazy loading
This creates duplicate files, broken srcset, and confusing cache behaviour. Pick one workflow:
| Approach | Best for |
|---|---|
| Local plugin (e.g. ShortPixel, Imagify) | Simple sites, no CDN |
| CDN-based optimisation (Bunny, Cloudflare, ImageKit) | Most sites — handles format conversion at edge |
| Build-time processing | Static sites, custom themes |
| WordPress core WebP + careful editor training | Minimalist approach |
8. Bulk optimisation safety rules
If uploads are enormous, optimise in batches:
# NEVER run an unconstrained bulk optimisation on production
# Always test on a single image first
# Always have a full backup before starting
# Check for backups before bulk processing
ls wp-content/uploads/backup*
Safe process
- Take a full backup (files + database)
- Test the tool on 5–10 images
- Verify those images still look correct on the frontend
- Process in small batches (50–100 images at a time)
- Check the frontend after each batch
- Run on a staging clone if possible
Bulk image tools are powerful enough to ruin a media library quickly. Some overwrite originals irreversibly. If the tool does not keep originals, make sure your backup is current and accessible.
9. Ongoing maintenance
- Train editors to resize images before upload (or provide presets)
- Set a maximum upload size in WordPress if needed
- Review largest images quarterly:
find wp-content/uploads -type f -size +2M - Monitor CDN bandwidth costs if using usage-based pricing
- Re-audit after major site redesigns that change image dimensions