Image Optimization for SEO in 2026: WebP, AVIF, Lazy Load, and the Size Rule
A practical guide to image optimization: choosing the right format (WebP vs AVIF vs JPEG), lossless compression, lazy loading, fetchpriority for LCP images, and correct width/height attributes to eliminate CLS.
Images are the root cause of poor LCP in the majority of cases we encounter during audits. A typical WordPress site ships 2–4 MB of images per page, while PageSpeed Insights recommends staying within 300–500 KB. Yet visual quality after optimization barely suffers — the difference is noticeable only when comparing side by side on a 4K display. The difference in load time, however, is 3–8 seconds on a mobile connection.
Let's go through it systematically: which format to choose, how to compress, how to set dimensions and loading attributes correctly — with concrete commands and numbers.
Formats: What to Choose in 2026
Three formats are relevant today:
JPEG — a veteran with 30 years of history. 100% browser support, but compression efficiency is worse than modern formats. A 200 KB JPEG equals roughly 80 KB in WebP at the same visual quality. Using JPEG today means paying twice as much in bandwidth and load time than you need to.
WebP — developed by Google in 2010, browser support reached 96%+ by 2026. Delivers 25–35% smaller file sizes compared to JPEG at comparable quality. Supports transparency (like PNG) and animation (like GIF). In most cases, it is the optimal choice for the support/compression trade-off.
AVIF — a successor to HEIC, based on the AV1 codec. Browser support reached 90%+ in 2025 (Safari added support in version 16). Compression is 40–50% better than JPEG and 15–20% better than WebP. For images with smooth gradients (photos, illustrations) it delivers a noticeable gain. The downside: encoding is significantly slower than WebP, which matters for systems with automated image processing.
| Format | Browser Support | Size vs JPEG | Transparency | Encoding Speed |
|---|---|---|---|---|
| JPEG | 100% | — | No | Fast |
| WebP | 96%+ | −25–35% | Yes | Fast |
| AVIF | 90%+ | −40–50% | Yes | Slow |
Practical rule for 2026: use WebP as the default format for all new content. For critical images (hero banners, LCP candidates) try AVIF via the <picture> tag with a WebP fallback. Keep JPEG only where conversion is technically impossible.
How to Compress Correctly
Converting the format alone does not guarantee results — quality settings matter. At quality=100, WebP can actually be heavier than JPEG. At quality=60, most users won't notice a difference.
Specific tools and commands:
cwebp (Google's official converter, install via package manager):
cwebp -q 80 input.jpg -o output.webp
Quality 75–85 is the optimal range for photos. For icons and flat-color illustrations you can go down to 65–70.
Squoosh CLI (from Google, runs via Node.js):
npx @squoosh/cli --webp '{"quality":82}' images/*.jpg
Lets you batch-process a folder and specify different parameters for WebP and AVIF in a single command.
avifenc (for AVIF):
avifenc --min 20 --max 35 input.png output.avif
The min/max parameters here work differently from quality — a lower value means better quality. The range 20–35 provides a good balance.
Online tools: Squoosh.app (browser-based, from Google, excellent for manual processing with a live preview), TinyPNG/TinyJPEG (work with WebP too), ImageOptim (macOS, batch processing).
Reference target sizes: blog photos — up to 100 KB, hero images — up to 150 KB, icons and UI elements — up to 20 KB. If a file exceeds these limits at acceptable quality, it is time to reduce the resolution.
Dimensions: The Most Common Mistake
The most widespread mistake we see in audits is uploading a 2000×1500 px image to a slot that displays it at 400×300 px. The browser downloads the full file and then scales it down via CSS. You are shipping 800 KB where 80 KB would do.
The srcset and sizes attributes solve this problem. They allow the browser to select the right image version for the specific screen.
Basic example:
<img
src="photo-800.webp"
srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, (max-width: 1200px) 50vw, 800px"
alt="Image description"
width="800"
height="600"
/>
How to read this: srcset lists available versions with their pixel widths. sizes describes how much space the image occupies at different viewport widths. The browser multiplies: if the screen is 390 px wide and the image fills 100% of that width, it needs a ~390 px version. It picks the nearest option from srcset — photo-400.webp.
For WordPress, srcset attributes are generated automatically when media files are uploaded through the standard uploader and sizes are configured in Settings → Media. However, source files must be uploaded at the correct resolution — WordPress will not degrade quality, but it also cannot create versions larger than the original.
Practical rule: prepare images in three sizes — 400 px, 800 px, and 1200–1600 px. For full-width blocks, add a 2000 px version for Retina displays.
Lazy Loading
The loading="lazy" attribute tells the browser that an image can be loaded when the user begins scrolling toward it, rather than immediately when the page opens.
<img src="photo.webp" loading="lazy" alt="..." width="800" height="600" />
Browser support is 97%+, no additional libraries needed. The effect is significant: on blog pages with 10–20 images, lazy loading reduces the initial download weight by a factor of 3–5.
An important exception: images in the above-the-fold area — those visible without scrolling on first load — must not have lazy loading applied. This hurts LCP, because the browser first builds the page layout, then "notices" that it needs to load the image, and only then fetches it.
What counts as above-the-fold: the first 600–700 pixels of the page on a mobile device (roughly one phone screen in portrait orientation). This is typically the hero image, the logo, and possibly the first banner. Everything below that — lazy.
How to determine this precisely: open Chrome DevTools, go to the Performance tab, and record a page load. The report will identify the LCP Element — that is the image that must not be lazy-loaded.
fetchpriority="high" for the LCP Image
The browser discovers images through different mechanisms. An image in an <img> tag in HTML is parsed when the page loads. An image set via CSS background-image is not. But even when the browser sees an <img>, it assigns different loading priorities based on the element's position on the page.
The fetchpriority="high" attribute explicitly tells the browser: "load this image first."
<img
src="hero.webp"
fetchpriority="high"
loading="eager"
alt="Main banner"
width="1200"
height="600"
/>
Where to use it: on exactly one image — whichever is the LCP candidate. This is typically the main hero banner on the homepage, the first image in a blog post, or the key product photo on a product card.
Why you cannot apply it everywhere: if you mark 5 images as high priority, the browser attempts to load all five simultaneously. Bandwidth contention cancels out the benefit. One fetchpriority="high" per page — no exceptions.
Support: Chrome 101+, Safari 17.2+, Firefox 128+. On unsupported browsers the attribute is silently ignored.
width and height Are Mandatory
The width and height attributes on an <img> tag are not about scaling. They are about CLS (Cumulative Layout Shift): how much page elements jump around during loading.
When the browser begins rendering the page, it does not know the size of an image before the image loads. If dimensions are not specified, the browser reserves space with a height of 0, then the image loads and "pushes" the page apart. Elements below shift down. A user reading the text loses their place. CLS increases.
When width="800" height="600" are specified, the browser reserves the correct space with a 4:3 aspect ratio from the very first render. The page does not jump. CLS = 0 for this element.
<!-- Bad: CLS is guaranteed -->
<img src="photo.webp" alt="Photo" />
<!-- Good: the browser reserves space immediately -->
<img src="photo.webp" alt="Photo" width="800" height="600" />
An important nuance: CSS can stretch or shrink the image freely — the width/height attributes only define the aspect ratio for space reservation. Therefore width="4" height="3" and width="800" height="600" produce the same effect, though convention is to write the actual size.
All popular CMS platforms can automatically insert width/height when uploading media — make sure this feature is enabled and that the uploaded files are not corrupted (dimensions cannot be detected for corrupted files).
Alt Tags
Briefly, because the topic deserves its own dedicated article: the alt attribute serves two purposes. The first is accessibility: screen readers read the alt text for users who cannot see the image. The second is SEO: search engines understand the image's content from the alt text, index images in Yandex Images and Google Images, and factor alt into page rankings. An empty alt attribute is a lost SEO signal on every single image.
Verification Tools
Google PageSpeed Insights (pagespeed.web.dev) — free, shows specific images with recommendations: "serve images in next-gen formats," "properly size images." Provides an estimated savings in KB.
Squoosh.app — Google's browser-based tool for manual compression with visual comparison. Ideal for individual images when you need to precisely evaluate the quality/size trade-off.
TinyPNG / TinyJPEG (tinypng.com) — work with WebP as well, batch processing via drag-and-drop, API available for automation.
ImageOptim (imageoptim.com) — macOS application, batch folder processing, supports all formats. Great for a final squeeze after conversion.
Chrome DevTools → Network tab → Images — shows the real weight and load time of every image on the page, filtered to media files only.
Image Optimization Checklist
- Convert all new images to WebP (quality 75–85)
- For hero and LCP images, test AVIF with a WebP fallback via
<picture> - Prepare three srcset sizes: 400 px, 800 px, 1200 px (plus 2000 px for full-width)
- Set
widthandheightattributes on every<img> - Apply
loading="lazy"to all images below the first screen - Apply
fetchpriority="high"andloading="eager"only to the LCP image - Fill in
alton every image — concisely and to the point - Verify results in PageSpeed Insights — target: green LCP (< 2.5 s) and CLS < 0.1
We analyze site speed as part of a technical SEO audit — discuss your project.