Optimizing images comes down to four moves: choose the format that suits the picture, export only the pixel widths the layout needs, compress each file, and control when it loads. Serve AVIF or WebP with a JPEG fallback, list widths in srcset, lazy load images below the fold, and give the hero fetchpriority high instead.
| Picture | Best format | Fallback |
|---|---|---|
| Photo | AVIF or WebP | JPEG |
| Screenshot with text | WebP lossless or PNG | PNG |
| Logo, icon, simple shapes | SVG | PNG |
| Short animation | Video (MP4 or WebM) | Animated WebP |
Updated
Images are usually the heaviest part of a page, and the hero is often the element measured for Largest Contentful Paint. Most of the saving comes from settings you choose once: format, widths, quality and loading behaviour. The builder below writes correct markup for those choices, and the checklist after it covers the rest.
Set the file name, widths, formats and where the image sits on the page. The builder writes picture and img markup with the right loading hints.
| Check | How | Why it helps |
|---|---|---|
| Modern format | picture with AVIF and WebP sources | Smaller files for the same look |
| Responsive widths | srcset with w descriptors plus sizes | Phones skip desktop sized files |
| Compression | Quality tuned by eye per image type | Fewer bytes per pixel |
| Dimensions | width and height attributes | Prevents layout shift |
| Lazy loading | loading="lazy" below the fold only | Saves data on long pages |
| Hero priority | fetchpriority="high" on the main image | Faster Largest Contentful Paint |
| Alt text | Describe content images; empty alt for decoration | Accessibility and image search |
The browser uses the first source type it supports. The img carries the size, alt text and loading hints for every format.
<picture>
<source type="image/avif"
srcset="/img/deck-800.avif 800w, /img/deck-1600.avif 1600w"
sizes="(max-width: 800px) 100vw, 800px">
<source type="image/webp"
srcset="/img/deck-800.webp 800w, /img/deck-1600.webp 1600w"
sizes="(max-width: 800px) 100vw, 800px">
<img src="/img/deck-1600.jpg" width="1600" height="900"
alt="Cedar deck with built-in bench at sunset"
loading="lazy" decoding="async">
</picture>A small Node script using the sharp package: every JPEG in ./src becomes three WebP widths in ./out.
import sharp from "sharp";
import { readdir, mkdir } from "node:fs/promises";
await mkdir("out", { recursive: true });
for (const file of await readdir("src")) {
if (!file.endsWith(".jpg")) continue;
const stem = file.replace(/\.jpg$/, "");
for (const width of [640, 1280, 1920]) {
await sharp(`src/${file}`)
.resize({ width, withoutEnlargement: true })
.webp({ quality: 75 })
.toFile(`out/${stem}-${width}.webp`);
}
}
web.dev's format guide sums it up: prefer vectors when the picture is shapes and text, and use a modern raster format for photos. PNG keeps every pixel exactly, which suits screenshots but makes photos needlessly large.
The picture element lets you offer new formats without breaking old browsers. The browser takes the first source whose type it understands and falls back to the img inside.
web.dev notes that sending desktop sized images to phones can use two to four times more data than needed, and suggests three to five sizes per image. List them with width descriptors in srcset and describe the layout in sizes.
Measure the rendered width in your layout rather than guessing. A card that is a third of the screen on desktop and full width on phones needs a sizes value that says exactly that.
Lazy loading saves bandwidth on long pages, so put loading lazy on images further down. For the main above the fold image, add fetchpriority high so it is requested before less important files.
decoding async lets the browser paint text before it finishes decoding a large picture. It is a hint, and browsers may ignore it.
Both beat JPEG for photos. AVIF is the newer format and often compresses further, while WebP encodes faster and has been supported longer. A safe pattern is a picture element offering AVIF first, then WebP, then a JPEG in the img tag for anything older.
It tells the browser how wide the image will be drawn, before layout happens, so it can pick the right file from srcset. Without sizes, a browser assumes the image fills the whole viewport and may download a much bigger file than needed.
Only images below the fold. Lazy loading waits until the browser knows where an image sits, which is a delay you do not want for anything people see straight away.
Lower the quality until you can just see a difference at full size, then step back up a notch. Busy photos hide compression well; smooth gradients, skies and text show artefacts sooner.
No. You can resize and convert in an editor or with a free in-browser tool, then write the markup by hand. Services help when you have thousands of images or user uploads to process automatically.
Related: Image compressor, WebP converter, Website image sizes, Core Web Vitals guide, HTML images guide.
Start for free or see all free tools. We.Inc is free to start, with no card needed. AI building is on paid plans from $20 a month.
We.Inc is an AI-powered website builder you can resell under your own brand. Launch a branded client dashboard, bill on Stripe Connect, and deliver AI-generated websites in minutes. White-label plans start at $99 a month for 25 client sites, with a 7-day free trial and no per-site fees.