Images are where most WordPress blogs bleed performance. Not themes. Not plugins. Not hosting. Images. On a typical blog post, images account for 50-80% of the total page weight. I’ve audited sites where a single blog post weighed 8MB, and 7.2MB of that was images. Uncompressed PNGs for screenshots. 4000px-wide JPEG photos displayed in a 800px content area. Hero images saved at 100% quality when 80% is visually identical.
This is your biggest win. The optimizations in this chapter can cut your page weight by 60-80% without any visible quality loss. I’ve taken client blog posts from 5MB to 800KB with the same images looking just as sharp. The visitors can’t tell the difference. The load time difference is dramatic.
Image Formats: When to Use Each
Choosing the right image format is the first decision, and it’s one most bloggers get wrong. They use whatever format their phone or screenshot tool saves by default. That default is almost never the best choice.
JPEG. The standard for photographs. Good compression, wide compatibility, no transparency support. JPEG is a lossy format, meaning it discards data to achieve smaller files. At 80-85% quality, the compression artifacts are invisible to the human eye on photographs. I still use JPEG as a fallback format, but WebP has replaced it as my primary choice.
PNG. The standard for graphics with transparency, sharp edges, or text. Screenshots, logos, diagrams, and icons. PNG is lossless by default, which means files are larger but quality is preserved perfectly. The problem: bloggers use PNG for photographs where JPEG or WebP would be 5-10x smaller. I see this constantly. Someone takes a screenshot, saves it as PNG (because their tool defaults to it), and the file is 2MB when a WebP at 85% quality would be 180KB with no visible difference.
WebP. Google’s modern format that handles both photographs and graphics. WebP typically produces files 25-35% smaller than JPEG at the same visual quality, and 25-30% smaller than PNG for graphics. Browser support is now universal. Every major browser (Chrome, Firefox, Safari, Edge) has supported WebP since 2020. There’s no reason not to use it as your primary format.
AVIF. The newest format, based on the AV1 video codec. AVIF produces files 20-30% smaller than WebP at the same quality. The compression is impressive, but there are tradeoffs. Encoding is slow (2-5x slower than WebP), which means your server or optimization plugin works harder. Browser support is good but not universal. Safari added AVIF support in iOS 16 and macOS Ventura. Older Apple devices don’t support it. I use AVIF as a first choice where supported, with WebP as fallback.
SVG. For simple graphics like icons, logos, and illustrations. SVG is vector-based, meaning it scales to any size without quality loss and files are tiny (usually 1-10KB for icons). If you’re using PNG for a simple logo or icon, stop. Convert it to SVG and save 90%+ of the file size.
My recommendation. Serve AVIF where supported, WebP as fallback, and JPEG/PNG as final fallback. This is exactly what ShortPixel and most WordPress image optimization plugins do automatically. You upload your original, and the plugin creates optimized versions in multiple formats. The server sends the best format each visitor’s browser can handle.
The WebP/AVIF Transition
If you’re still serving original JPEGs and PNGs to your visitors, you’re sending files that are 30-50% larger than they need to be. The transition to modern formats is painless with the right setup.
WordPress native support. WordPress added WebP upload support in version 5.8 (2021) and AVIF support in version 6.5 (2024). You can now upload WebP and AVIF files directly in the media library. But that’s only half the solution. You also need to convert your existing images and serve the right format to each browser.
Plugin-based conversion. This is the approach I recommend. Install ShortPixel or Imagify, and it will compress your images on upload and generate WebP and AVIF versions automatically. It stores both versions, and your server sends the right one based on the browser’s Accept header.
ShortPixel is my pick because it handles the full pipeline: compression, format conversion, and serving. The pay-as-you-go pricing means you only pay for what you use, typically $4-10/month for a blog with regular uploads. They also offer a one-time bulk optimization when you first install, so your entire existing media library gets converted.
CDN-based conversion. If you use Cloudflare (free plan or higher), their Polish feature can convert images to WebP on the fly. Bunny CDN offers similar on-the-fly optimization. The advantage is zero server load for conversion. The disadvantage is you’re relying on the CDN to always get it right, and you have less control over quality settings.
Fallback handling. When you serve modern formats, you need fallbacks for the rare browser that doesn’t support them. The <picture> element handles this natively in HTML. Most WordPress optimization plugins generate the proper <picture> tags automatically. If you’re doing it manually:
<picture>
<source srcset="image.avif" type="image/avif">
<source srcset="image.webp" type="image/webp">
<img src="image.jpg" alt="Description" width="800" height="450">
</picture>
The browser picks the first format it supports. AVIF if available, WebP if not, JPEG as the final fallback. Clean and reliable.
Compression: The Quality Sweet Spot
Compression is where file size meets visual quality. Too little compression and your files are unnecessarily large. Too much and your images look like they were faxed in 1995.
After testing hundreds of images at different quality levels, I’ve found the sweet spot: 80-85% quality for JPEG and WebP, 70-80% for AVIF (AVIF handles lower quality settings better).
The numbers. A 2000×1200 photograph at different quality levels:
JPEG 100% quality: 1.8MB
JPEG 85% quality: 420KB (77% smaller)
JPEG 80% quality: 320KB (82% smaller)
WebP 85% quality: 280KB (84% smaller than JPEG 100%)
AVIF 75% quality: 190KB (89% smaller than JPEG 100%)
From 1.8MB to 190KB with no visible quality difference. That’s a 10x reduction. On a blog post with 5 images, that’s the difference between a 9MB page and a 950KB page. On mobile, that’s the difference between 8 seconds and 2 seconds.
I always test with a side-by-side comparison before committing to a quality setting. Open the original and the compressed version on a high-resolution display and look for artifacts. At 80-85%, you won’t find them on photographs. You might see slight softening on images with text or sharp edges, which is why I use PNG/WebP for screenshots and keep quality at 85% for those.
Lossy vs. lossless for WebP. WebP supports both lossy and lossless compression. Use lossy for photographs (smaller files, no visible quality loss). Use lossless for screenshots, graphics with text, or anything where pixel-perfect accuracy matters. Most optimization plugins let you choose this per image or set a default.
Don’t compress twice. If you compress an image in Photoshop at 85% and then your WordPress plugin compresses it again at 85%, you’re degrading quality without meaningful size reduction. Either compress during export from your editing tool OR let the WordPress plugin handle it. Not both. I prefer letting the WordPress plugin handle all compression so I have one consistent pipeline.
Responsive Images: Stop Sending 2000px Images to Phones
This is the optimization that makes me genuinely frustrated when I see it missing. A 2000px-wide hero image looks great on a 27-inch desktop monitor. But 70% of your visitors are on phones with screens that are 375-414 pixels wide. Sending them a 2000px image means they’re downloading 4x more data than they need. The browser just shrinks it down and throws away the extra pixels.
WordPress has handled responsive images automatically since version 4.4 (2015). When you upload an image, WordPress creates multiple sizes: thumbnail (150px), medium (300px), medium-large (768px), large (1024px), and full size. It adds the srcset and sizes attributes to your <img> tags so the browser can choose the right size for the viewer’s screen.
But it only works if you let it. Some themes and plugins override WordPress’s responsive image behavior. Some page builders insert images without srcset. Some people manually specify the full-size image URL, bypassing the automatic sizing. Check your blog posts in Chrome DevTools. Right-click an image, inspect it, and look for the srcset attribute. If it’s missing, your images aren’t responsive.
Custom sizes matter. WordPress’s default sizes might not match your theme’s content area. If your blog content area is 730px wide, the “large” size at 1024px is bigger than needed for standard views, but you want at least 1460px for Retina displays. Configure your image sizes in Settings > Media to match your theme’s actual layout widths. And add a 2x version for Retina screens.
The sizes attribute. This tells the browser how wide the image will be displayed at different viewport widths. Without a correct sizes attribute, the browser has to guess, and it often guesses wrong (defaulting to the viewport width). Your theme should generate correct sizes attributes. Check it. If the sizes value says 100vw on an image that only takes up 60% of the viewport, the browser is downloading a larger image than needed.
Lazy Loading: Native Wins
Lazy loading delays the download of off-screen images until the user scrolls near them. Instead of loading all 15 images on a blog post at once, the browser only loads the 2-3 visible above the fold, then loads the rest as the user scrolls.
Native browser lazy loading. Since 2020, all major browsers support the loading="lazy" attribute on images. WordPress adds this automatically to all images since version 5.5. It’s simple, reliable, and adds zero JavaScript overhead.
<img src="photo.webp" loading="lazy" width="800" height="450" alt="Description">
That’s it. No plugin needed. No JavaScript library. The browser handles everything.
One critical rule: don’t lazy load your LCP image. The Largest Contentful Paint element should load as fast as possible. If your hero image or first featured image is your LCP element (check this in PageSpeed Insights), it should NOT have loading="lazy". WordPress 6.3+ automatically removes lazy loading from the first content image, but verify this on your site. Your LCP image should have loading="eager" (or no loading attribute at all) and ideally a fetchpriority="high" attribute.
JavaScript-based lazy loading. Some performance plugins offer their own JavaScript lazy loading. FlyingPress uses a hybrid approach that adds a tiny placeholder until the image enters the viewport, which can prevent layout shifts. But for most sites, native browser lazy loading is sufficient and the lightest option.
Lazy load iframes too. YouTube embeds, Google Maps, and other iframes are heavy resources that should be lazy loaded. Add loading="lazy" to your iframes, or use a plugin that converts YouTube embeds to a lightweight placeholder that only loads the full player when clicked. FlyingPress does this automatically, and it can save 500KB+ per YouTube embed.
Image CDN Services
An image CDN processes and delivers your images from edge servers worldwide. Instead of your origin server resizing and compressing images on every request, the CDN does it once and caches the result. The visitor gets the optimized image from a server near them.
Cloudflare Image Resizing. Available on Cloudflare Pro plans ($20/month) and higher. It can resize, compress, and convert images on the fly. Pairs well with Cloudflare’s free CDN. Good option if you’re already on Cloudflare.
ShortPixel Adaptive Images. Serves responsive, optimized images from ShortPixel’s CDN. It detects the visitor’s screen size and serves the right dimensions automatically. Useful if you don’t want to worry about srcset configuration.
Bunny Optimizer. Bunny CDN includes an image optimization and delivery feature. It compresses and converts images on the edge, serves WebP/AVIF where supported, and handles responsive sizing. Pricing is usage-based and extremely competitive. Bunny is what I recommend if you want a standalone image CDN without the complexity of Cloudflare.
When to use an image CDN vs. local optimization. For most WordPress blogs, local optimization (ShortPixel compressing and converting on upload) combined with a general CDN (Cloudflare) is sufficient. Image CDNs add the most value when you have thousands of images that weren’t optimized on upload, or when you need real-time resizing for different devices without generating multiple sizes locally.
Screenshot and Featured Image Workflow
Most image problems start before the image reaches WordPress. The way you create and export images determines your starting file size. Here’s the workflow I use for every piece of visual content.
Screenshots. I use CleanShot X on Mac (Snipping Tool on Windows works fine too). I capture at 2x resolution (Retina), then export as WebP at 85% quality. For a typical full-screen screenshot, this produces a file of 150-300KB instead of the 1-2MB PNG that screenshot tools save by default. If the screenshot contains text that needs to be crisp, I use WebP lossless, which is still 40-60% smaller than PNG.
Featured images and hero images. I create these at exactly 2x my content area width. If my blog content is 730px wide, I create the image at 1460px wide. This gives Retina displays a sharp image without wasting pixels on unnecessary size. Export as JPEG at 85% if it’s a photograph, WebP at 85% for everything else.
Don’t upload full-resolution camera photos. A photo straight from your phone is typically 4000-6000px wide and 3-8MB. There is no WordPress theme that needs a 6000px image. Resize before uploading. I batch-resize in Preview on Mac (select all, Tools > Adjust Size) or use ImageMagick for command-line batch processing.
Name your files descriptively. IMG_4392.jpg tells nobody anything. wordpress-speed-settings-screenshot.webp helps with SEO and makes your media library manageable. I name every file before upload. It takes 3 seconds per image and saves confusion later.
Strip EXIF data. Photographs contain metadata: camera model, GPS coordinates, date, exposure settings. This adds 5-50KB per image and serves no purpose on the web. Most optimization plugins strip EXIF automatically. If yours doesn’t, add it to your export settings.
The Image Optimization Checklist
This is the checklist I run on every client site. It covers the full pipeline from image creation to delivery.
Before upload:
- [ ] Image is sized to 2x the display width (not larger)
- [ ] Export quality is 80-85% for JPEG/WebP, 70-80% for AVIF
- [ ] File is named descriptively with hyphens (not underscores or spaces)
- [ ] EXIF data is stripped
- [ ] Format matches content type (JPEG/WebP for photos, PNG/WebP for screenshots with text, SVG for icons/logos)
WordPress configuration:
- [ ] Image optimization plugin installed and configured (ShortPixel recommended)
- [ ] WebP and AVIF conversion enabled
- [ ] Lazy loading active for all below-fold images
- [ ] LCP image is NOT lazy loaded (has loading=”eager” or fetchpriority=”high”)
- [ ] srcset and sizes attributes present on all content images
- [ ] Image sizes in Settings > Media match your theme’s layout widths
- [ ] Post revisions of images cleaned up (old versions removed)
Delivery:
- [ ] CDN is active and serving images from edge locations
- [ ] Browser caching headers set for images (max-age of at least 1 year for immutable files)
- [ ] WebP/AVIF is being served to supporting browsers (check with Chrome DevTools Network tab, filter by “Img” type, check the “Type” column)
Verification:
- [ ] Total page weight for a typical blog post is under 1MB
- [ ] Image weight per post is under 500KB
- [ ] LCP score has improved after optimization (re-test in PageSpeed Insights)
- [ ] No images are being served at sizes larger than their display size
I run this checklist when I first set up a site and then spot-check quarterly. Image bloat creeps back in when authors upload without following the workflow, when plugins update and change settings, or when new content types are added without considering image sizes.
The cumulative impact of proper image optimization is the single biggest speed improvement most blogs can make. I’ve seen sites cut their total page weight by 70% just from images, and that weight reduction translates directly into faster load times, better Core Web Vitals scores, and lower bandwidth costs. On a site with 100,000 monthly pageviews, proper image optimization can save 200-400GB of monthly bandwidth. At CDN pricing of $0.01-0.05 per GB, that’s real money too.
Images are the low-hanging fruit of performance. Not every optimization in this course will be easy, but this one is. Get your image pipeline right, and you’ll see immediate, measurable results the next time you run PageSpeed Insights.
Chapter Checklist
- [ ] Audited 5 recent blog posts for image file sizes (Chrome DevTools > Network > Img filter)
- [ ] Installed and configured ShortPixel (or alternative image optimization plugin)
- [ ] Enabled WebP and AVIF conversion
- [ ] Verified native lazy loading is working (inspect images, look for loading=”lazy”)
- [ ] Confirmed LCP image is not lazy loaded
- [ ] Checked that srcset attributes are present on content images
- [ ] Established an image export workflow (format, quality, sizing)
- [ ] Bulk optimized existing media library through your optimization plugin
- [ ] Re-tested PageSpeed Insights to measure improvement
Chapter Exercise
Pick your most image-heavy blog post and measure its current image weight. Open Chrome DevTools, go to the Network tab, reload the page, and filter by “Img”:
- Number of images on the page: ___
- Total image weight (transferred): ___
- Largest single image file size: ___
- Largest image display width: ___px
- Largest image actual width: ___px (check the image’s natural dimensions)
If the actual width is more than 2x the display width, you’re serving oversized images. If total image weight is over 500KB, you need compression and format conversion.
Now install ShortPixel (or your preferred tool), bulk optimize the post’s images, and re-test:
- Total image weight after optimization: ___
- Percentage reduction: ___%
- PageSpeed mobile score before: ___
- PageSpeed mobile score after: ___
That percentage reduction is what you’ll get across your entire site. Multiply it by your total monthly bandwidth, and you’ll see why image optimization is the single biggest performance win for most WordPress blogs.
Disclaimer: This site is reader-supported. If you buy through some links, I may earn a small commission at no extra cost to you. I only recommend tools I trust and would use myself. Your support helps keep gauravtiwari.org free and focused on real-world advice. Thanks. - Gaurav Tiwari