Why responsive images matter
Serving desktop-sized images to mobile devices can consume 2–4x more data than necessary. By evaluating the display capabilities of a user's device and choosing the optimal image from a set of candidates, you can serve smaller images to devices with smaller screens. This reduces data usage and can also improve your page's Largest Contentful Paint (LCP) if an image is the LCP element, since a smaller resource loads faster. Reduced bandwidth contention can also speed up other resources on the page.
Generating resized images
Two popular tools for resizing images are the sharp npm package and the ImageMagick CLI tool. The sharp package is well-suited for automating resizing in build scripts and tools, while ImageMagick is convenient for one-time resizing from the command line.
To use sharp, save a Node script in your project and run it to convert your images:
const sharp = require('sharp');
const fs = require('fs');
const directory = './images';
fs.readdirSync(directory).forEach(file => {
sharp(`${directory}/${file}`)
.resize(200, 100) // width, height
.toFile(`${directory}/${file}-small.jpg`);
});
To resize an image to 33% of its original size with ImageMagick:
convert -resize 33% flower.jpg flower-small.jpg
To resize an image to fit within a 300x200 pixel space:
# macOS/Linux
convert flower.jpg -resize 300x200 flower-small.jpg
# Windows
magick convert flower.jpg -resize 300x200 flower-small.jpg
How many versions to create
There is no single correct answer, but serving 3–5 different sizes per image is common. More sizes improve performance but require additional server storage and slightly more HTML. Image services like Thumbor (open-source) and Cloudinary are alternatives that offer on-demand manipulation; Thumbor requires server installation while Cloudinary is fully managed.
Using srcset and sizes
The <img> tag's src, srcset, and sizes attributes work together to let the browser pick the best image version:
| Before | After |
|---|---|
| <img src="flower-large.jpg"> | <img src="flower-large.jpg"> |
The src attribute acts as a fallback for browsers that don't support srcset or sizes; those browsers load the resource specified in src.
The srcset attribute is a comma-separated list of image filenames with width or density descriptors. Width descriptors (e.g., 480w, 1080w) tell the browser an image's width without requiring a download to determine it.
The sizes attribute tells the browser how wide the image will be displayed. It does not affect display size, so CSS is still needed for that. The browser uses this information along with the device's dimensions and pixel density to decide which image to download. Since sizes and srcset were introduced together, browsers support either both or neither, and unsupported browsers fall back to src.
The same concepts can be extended for art direction—serving completely different images to different viewports—and for multiple slot sizes when a site uses different layouts per viewport size.
Verifying your implementation
After implementing responsive images, run the Lighthouse Performance Audit (Lighthouse > Options > Performance) and check the Properly size images audit. The results list images that still need resizing.



