On most websites, images make up the biggest share of the bytes downloaded, and the largest image above the fold is usually the Largest Contentful Paint element. Getting images right is therefore the quickest way to make pages feel faster, especially on phones. The good news: modern HTML, WordPress and Next.js do most of the work once you give them the right information.
Choose the formatLink to this section
| Format | Best for | Notes |
|---|---|---|
| WebP | Photos and graphics | Typically 25–35% smaller than JPEG at similar quality; supported by all current browsers |
| AVIF | Large photos where savings matter | Often smaller than WebP, but slower to encode |
| JPEG | Fallback, very old systems | Still fine when a pipeline can't produce WebP |
| PNG | Screenshots with sharp text, images needing exact pixels | Large for photos; try lossless WebP first |
| SVG | Logos, icons, illustrations | Scales perfectly; sanitize uploaded SVGs, as they can contain scripts |
For one-off assets you upload yourself, such as a hero image or a team photo, convert to WebP before uploading and compare the before and after sizes with the image to WebP converter. It runs in the browser, so originals stay on your machine.
Size before formatLink to this section
Format choice matters less than dimensions. A 4000-pixel camera photo displayed 800 pixels wide wastes most of its bytes, whatever the format. Check what you actually have with the media previewer, which shows real pixel dimensions and aspect ratio, then resize to roughly twice the largest display width for sharp results on high-density screens.
srcset and sizes: let the browser chooseLink to this section
A responsive image offers several widths and tells the browser how wide it will be shown. The browser picks the smallest file that looks sharp on the current screen.
<img
src="/img/hall-800.webp"
srcset="/img/hall-400.webp 400w, /img/hall-800.webp 800w, /img/hall-1200.webp 1200w, /img/hall-1600.webp 1600w"
sizes="(min-width: 64rem) 50vw, 100vw"
width="1600"
height="1000"
alt="Exhibition stand with a curved LED wall and a meeting lounge"
/>srcsetlists the files and their real pixel widths (400wmeans 400 pixels wide).sizesdescribes the display width: half the viewport on large screens, the full width otherwise. Withoutsizes, the browser assumes100vwand often downloads a file far larger than needed.widthandheightare the intrinsic size. The browser uses their ratio to reserve space before the image loads, which prevents layout shift.
Getting sizes wrong is the most common mistake. If a card image is shown at 33% width on desktop, say so: sizes="(min-width: 72rem) 33vw, (min-width: 48rem) 50vw, 100vw". The CSS layout and sizes should match.
Art direction with pictureLink to this section
When the image itself should change, for example a tighter crop on mobile, use <picture>:
<picture>
<source media="(max-width: 40rem)" srcset="/img/hero-mobile.avif" type="image/avif" />
<source media="(max-width: 40rem)" srcset="/img/hero-mobile.webp" type="image/webp" />
<source srcset="/img/hero-wide.avif" type="image/avif" />
<img src="/img/hero-wide.webp" width="1600" height="700" alt="Showroom interior" fetchpriority="high" />
</picture>The browser uses the first source it supports and whose media query matches, so list AVIF before WebP.
Loading priorityLink to this section
The hero image: load earlyLink to this section
The LCP image should start downloading immediately:
- Don't lazy-load it.
- Add
fetchpriority="high". - Use a real
<img>, not a CSSbackground-image; the browser discovers background images late. - If it's injected by JavaScript or a slider, add a
<link rel="preload" as="image" imagesrcset="…" imagesizes="…">in the head, or better, render it in the HTML.
Everything else: lazy-loadLink to this section
<img src="/img/gallery-1.webp" loading="lazy" decoding="async" width="800" height="600" alt="…" />loading="lazy" defers images until they approach the viewport. decoding="async" lets the browser decode them off the main thread. Don't lazy-load images that are visible on load; it delays them.
Preventing layout shiftLink to this section
Every image needs reserved space:
widthandheightattributes, or- CSS
aspect-ratioon the container, with the image set towidth: 100%; height: 100%; object-fit: cover.
.card__media { aspect-ratio: 16 / 9; overflow: hidden; }
.card__media img { width: 100%; height: 100%; object-fit: cover; }Responsive layouts can still keep the correct ratio: setting height: auto in CSS together with the width and height attributes keeps the proportions while the width changes.
In WordPressLink to this section
WordPress handles a lot automatically when themes use its functions:
wp_get_attachment_image()and the Image block outputsrcset,sizes,width,height,loading="lazy"anddecoding="async".- Since 6.3, WordPress adds
fetchpriority="high"to the image it believes is the LCP and skips lazy-loading for the first content images. Check that it picks the right one, especially with sliders or page builders. - Register sizes that match your layout with
add_image_size(), and set thesizesattribute when the default is wrong:
add_filter( 'wp_calculate_image_sizes', function ( $sizes, $size, $src, $meta, $attachment_id ) {
if ( is_singular( 'property' ) ) {
return '(min-width: 1024px) 50vw, 100vw';
}
return $sizes;
}, 10, 5 );- WordPress creates WebP or AVIF sub-sizes when the server's image library supports them and you enable it with the
image_editor_output_formatfilter, or via a plugin. Many image CDNs convert on the fly instead.
Large galleries, such as exhibition or art portfolios like Nucleus Exhibitions and Greenaway Mosaics, benefit most: dozens of images per page, where correct sizes and lazy-loading cut transfer dramatically.
In Next.jsLink to this section
The next/image component generates srcset, converts to WebP or AVIF, lazy-loads by default and requires dimensions:
import Image from "next/image";
<Image
src={post.image.url}
alt={post.image.alt}
width={post.image.width}
height={post.image.height}
sizes="(min-width: 72rem) 33vw, (min-width: 48rem) 50vw, 100vw"
priority={isFirst}
/>- Set
sizeswhenever the image isn't full width; otherwise large files are generated and served. - Use
priorityon the LCP image only. It disables lazy-loading and preloads the image. - Allow remote hosts such as your WordPress media domain in
images.remotePatterns. - Enable AVIF with
images: { formats: ['image/avif', 'image/webp'] }innext.config.
Alt textLink to this section
Alt text is for people who can't see the image and for search engines:
- Describe what matters in context, in a sentence: "Exhibition stand with a curved LED wall and a meeting lounge", not "stand1.jpg" or "image".
- Use
alt=""for purely decorative images so screen readers skip them. - Don't stuff keywords; describe the image.
ChecklistLink to this section
- ☐ Images resized to about twice their largest display width.
- ☐ WebP (or AVIF) served; originals kept for editing.
- ☐
srcsetand asizesvalue that matches the layout. - ☐ Hero image eager with
fetchpriority="high"; others lazy. - ☐
width/heightoraspect-ratioon every image. - ☐ Meaningful alt text; decorative images
alt="". - ☐ Verified in PageSpeed Insights: LCP element and "Properly size images".
Auditing an existing site's imagesLink to this section
On an existing site, start with an audit rather than a blanket change:
- Find the LCP image on key templates, such as the home page, a category or listing page, and a detail page, using PageSpeed Insights or the Performance panel in Chrome DevTools. Confirm it isn't lazy-loaded, and that it's an
<img>the browser can discover in the HTML. - Check transfer sizes. In the Network panel, filter by images and sort by size. Anything over 200 KB above the fold deserves a look; anything over 500 KB almost always has a fix.
- Compare rendered and intrinsic sizes. Hover over an image in the Elements panel: DevTools shows the displayed size and the file's real size. A 2,400-pixel file shown at 360 pixels on a phone means
sizesis wrong or missing. - Look for layout shift. The Performance panel marks layout shifts; images without dimensions are the usual cause.
- Check formats. If the Network panel shows JPEG and PNG for photos, WebP conversion is a quick win.
Fix the templates in order of traffic: the pages most visitors land on first. On WordPress, many fixes are in the theme, not the content. Correct the sizes filter, register sizes that match the layout and fix the hero template, and every page using that template improves at once.
Uploaded contentLink to this section
Editors upload whatever they have, often straight from a camera or a design tool. Set a reasonable maximum size so WordPress scales huge uploads down (WordPress does this by default for images above 2,560 pixels with the big_image_size_threshold filter), and give editors a simple guideline: export images at around 2,000 pixels wide, in WebP or high-quality JPEG.
Common problemsLink to this section
- Images look blurry on phones. The largest
srcsetcandidate is smaller than the display width times the device pixel ratio. Add a larger size. - The browser downloads huge files for small cards.
sizesis missing or says100vw. - LCP got worse after adding lazy-loading. The hero image is lazy. Make it eager with high priority.
- Layout jumps as images load. Missing dimensions or aspect-ratio.
Frequently asked questionsLink to this section
Should I serve AVIF everywhere?Link to this section
Not necessarily. AVIF encoding is slower and gains are smaller on small images. WebP everywhere with AVIF for large hero and gallery images is a good balance.
Do I still need JPEG fallbacks?Link to this section
For public websites today, WebP is supported by all current browsers. Keep fallbacks only if your audience includes old devices or embedded browsers you know about.
Is a CDN worth it for images?Link to this section
Usually yes. Image CDNs resize and convert on the fly and cache close to visitors, which removes most of the manual work above.
How do images affect SEO?Link to this section
Faster pages help page experience, and descriptive file names, alt text and surrounding text help images appear in image search.
Continue with the Core Web Vitals guide or ask for a performance review.
Test yourself
3 quick questions on this lesson.
Finished this lesson?
Mark it complete to track your progress through the learning paths.