On most business websites, images are the heaviest thing on the page. A single photo straight from a camera or stock library can outweigh a page’s text, code and fonts combined, and it’s often the very thing a visitor is waiting to see. That makes image optimisation for websites one of the cheapest, most dependable speed wins there is, and one of the easiest to undo with one careless upload.
This guide is for the marketers, editors and digital teams who upload images. It follows Google’s web.dev guidance and MDN, from choosing formats to the safeguards that stop oversized photos reaching visitors.
Image optimisation for websites: the short answer
- Choose the format by content. Photos in WebP or AVIF, logos and icons in SVG, PNG for lossless graphics, JPEG as the fallback.
- Export at the size the image is displayed, up to twice that width for sharp screens. Never upload the camera original.
- Use
srcsetandsizesso phones download smaller files than desktops. - Always set
widthandheightso the layout doesn’t jump. - Lazy-load images below the first screen, never the main (LCP) image. Give that one
fetchpriority="high"instead. - Let the build do the work, with automatic resizing and format conversion.
Choose the right format: JPEG, PNG, WebP, AVIF or SVG
Pick the format by what’s in the picture, not by habit.
| Format | Best for | Transparency | Watch out for |
|---|---|---|---|
| JPEG | Photos, where maximum compatibility matters | No | Larger than WebP or AVIF at similar quality |
| PNG | Screenshots, diagrams, flat graphics | Yes | Very large when used for photos |
| WebP | Photos and graphics; a dependable default | Yes | Often a little larger than AVIF |
| AVIF | Photos, especially large hero and product shots | Yes | Slower to encode; can smooth away fine texture |
| SVG | Logos, icons, simple illustrations | Yes | Vector artwork only; uploads need sanitising |
WebP vs AVIF
At the time of writing (July 2026), the current versions of Chrome, Edge, Firefox and Safari all support both, and both usually beat JPEG on file size at similar quality. AVIF often produces smaller files than WebP, but not every time. It’s slower to encode, and at aggressive settings it can blur fine texture such as fabric or hair. WebP is quicker and more predictable.
The practical answer is to generate both and let the browser choose, using <picture> with one <source> per format, AVIF first (the browser takes the first format it supports), and an <img> fallback. If you can only produce one, WebP is the safe choice.
Compress by eye, not by number
When you compress images for a website, quality numbers aren’t comparable: “80” in one tool or format isn’t “80” in another. Export a typical image at a few levels, view them at 100% zoom, and use the lowest setting where you can’t see a difference. Strip camera metadata too: it adds weight and can reveal where the photo was taken.
SVG, animation and text in images
- Logos and icons belong in SVG: usually tiny files that stay sharp at any size. SVG files can contain scripts, so WordPress doesn’t accept SVG uploads by default; if you enable them, sanitise every file.
- Animated GIFs are enormous for what they show. web.dev recommends replacing them with a short, muted, looping video, usually a fraction of the size.
- Text baked into an image blurs when zoomed, can’t be selected or translated, screen readers only get what the alt text repeats, and a multilingual site needs a copy for every language. Put the words in the page instead.
Size images for the space they fill
The bigger problem is usually size, not format: a 4,000-pixel photo displayed in a 400-pixel card. The browser downloads every pixel, then throws most of them away.
Work out the size you actually need
There’s no single best image size for a website. The right size is the width the image fills on screen, in CSS pixels, multiplied by the screen’s pixel density. High-density screens use two or three device pixels per CSS pixel, so an image shown 600 pixels wide needs about 1,200 to look crisp. Many teams cap at 2x: beyond that, the extra sharpness is hard to see, but the file keeps growing.
Starting points for common slots:
| Image slot | Typical display width | Export width |
|---|---|---|
| Full-width hero | Up to the full browser width | 1,920–2,560 px, plus smaller versions for phones |
| Image in an article column | 700–900 px | 1,400–1,800 px |
| Card or thumbnail | 300–450 px | 600–900 px |
| Logo or icon | Any | SVG, so pixel size doesn’t apply |
Responsive images: srcset and sizes
The srcset attribute lists the same image at several widths (say 800, 1,600 and 2,400 pixels), and sizes tells the browser how wide it will display, such as half the screen on large displays and the full width below that. The browser factors in pixel density and downloads the smallest file that will look sharp.
The common mistake is srcset without an accurate sizes. Without one, the browser assumes the image spans the full width of the browser window, so a small card image can pull down a file several times larger than needed. A CMS can generate srcset but can’t always know your layout: WordPress bases its default sizes on the image’s own width, not the column it sits in. Since version 6.7 it adds sizes="auto" to lazy-loaded images, which lets browsers that support it use the real layout width. Check templates with grids and sidebars.
Art direction is a different job. When a wide landscape hero becomes a thin strip on a phone, use <picture> with media conditions to serve a different crop, not just a smaller file.
Set width and height so nothing jumps
Give every image width and height attributes that match the file’s proportions. Browsers use them to reserve space before the image arrives, while CSS (max-width: 100%; height: auto) keeps it responsive. Without them, everything below the image jumps when it loads: a textbook cause of Cumulative Layout Shift, which Google rates as good at 0.1 or less. For CSS backgrounds and embeds, use the aspect-ratio property. Core Web Vitals explained covers layout shift’s other causes.
Lazy loading images: below the fold, never the hero
The loading="lazy" attribute, supported natively in all major browsers, holds back images until the visitor scrolls near them, saving data and freeing the network for what’s on screen.
On the wrong image, it backfires. The browser only fetches a lazy image once layout confirms it’s near the viewport, so a lazy-loaded hero starts downloading late and Largest Contentful Paint suffers. web.dev advises against lazy-loading anything visible when the page first loads.
| Where the image sits | Loading | Priority |
|---|---|---|
| The hero or main (LCP) image | Default (eager) | High |
| Other images visible on first load | Default (eager) | Default |
| Everything further down the page | Lazy | Default |
Give the main image priority
fetchpriority="high" tells the browser an image matters more than the other files competing for bandwidth. Use it on one image per page, the likely LCP element; marking several dilutes the effect. Current major browsers support it; older ones ignore it.
If the hero is a CSS background, the browser only finds it after the stylesheet has loaded and been applied. Make it a real <img>, or preload it with <link rel="preload" as="image" fetchpriority="high">. Hero carousels add another problem: several large images compete, and the first slide often arrives late. If you keep one, give the hidden slides fetchpriority="low".
Build safeguards so one upload can’t slow the site
The next person to upload a photo may never read your guidelines, so make the right outcome automatic.
- Automatic resizing. WordPress creates smaller copies of each upload and outputs a
srcsetfor images placed through the editor. Since version 5.3 it also scales down uploads over 2,560 pixels on the longest side, by default. - Automatic loading hints. WordPress lazy-loads images, tries to skip the first ones and, since version 6.3, gives high priority to the likely hero. Page builders and sliders can fool the guess, so check it. How to speed up a WordPress website covers this alongside plugins and caching.
- Format conversion. WordPress accepts WebP uploads (since 5.8) and AVIF (since 6.5) where the server supports them. Converting JPEG uploads automatically usually takes a plugin, your host’s image tools or an image CDN.
- Image CDNs resize, convert and compress on request, serve AVIF or WebP to browsers that accept them, and cache the results close to visitors. Website caching and CDNs explained shows where this fits.
- Template-controlled image slots. Give each slot a fixed aspect ratio and let the template decide size and crop, with a focal point editors can set. They choose the picture; the system handles the rest.
- Upload limits and prompts. Cap the file size, and make alt text a prompted field rather than an optional extra.
Product galleries: a special case
Product pages often carry more images than any other template, and shoppers want detail. E-commerce product page design covers what a gallery should show; here is how to load it.
- The main product image is often the LCP element. Load it eagerly with high priority and a
srcsetsized for the gallery’s real width. - Thumbnails get their own small files, not the full-size image shrunk by the browser.
- Other gallery images wait until the visitor swipes, and the high-resolution zoom version until someone actually zooms.
- Keep one aspect ratio across the catalogue, such as square or 4:5, so the grid stays tidy and switching colour variants doesn’t shift the page.
- In listing grids, lazy-load everything except the first row, which is visible on arrival.
Check what’s already live
Free tools will find the worst offenders:
- Run key pages through PageSpeed Insights on mobile. It names the LCP element and flags images that are oversized, poorly compressed, in older formats or missing dimensions. How to read a PageSpeed Insights report explains the rest.
- Open Chrome DevTools, filter the Network panel by Img, reload and sort by size.
- Compare displayed and actual size. In the Elements panel, hover over an image’s source to see its rendered and intrinsic sizes. A 3,000-pixel file shown at 350 pixels is a quick win.
- Inspect the hero. Confirm it isn’t lazy-loaded, has high priority and isn’t a CSS background found late.
- Watch Search Console’s Core Web Vitals report. It uses data from real Chrome users over the previous 28 days (when a site has enough traffic), so fixes take weeks to show.
Fix templates before individual images: one change to a card or hero component repairs every page using it. The website speed optimisation guide puts images in context with hosting, code and scripts.
A pre-upload checklist
Keep this next to whoever uploads images:
Alt text also helps Google understand images, but it’s written for screen reader users first; our web accessibility guide covers how.
What to do next
Sites slow down one upload at a time, so image optimisation works best as a system rather than an occasional clean-up.
A new site is the cheapest moment to get this right: image slots, sizes, formats and loading decided in the design and built into the templates, so your team can upload freely without undoing the work. That’s how we approach website design and development, with performance built in alongside design, content and SEO rather than patched on after launch. If your current site feels heavy, a free website audit will show whether images are to blame.