Skip to the tool workspace
Browser 123

How-to Images

How to get images small enough for a fast page

A page is slow because of its images. Resize each one to twice the size it is shown at, then encode it well: the commands, measured sizes and quality scores for JPEG, WebP and AVIF, and the HTML that serves the right file.

When a page is slow, the images are nearly always the reason, and nearly always for the same one: they are far bigger than the space they are shown in. A camera photo is 5000 pixels wide; the column it sits in is 800. So there are two jobs, in this order. Resize each image to twice the size it is shown at, at most, then encode it well.

Three photos compressed in the browser, each showing its new size and how much smaller it got

Drop the images in and each one shows its new size and the saving.

The first job does most of the work. A 5184 × 3456 camera photo of 11.1 MB came out at 2.58 MB when we re-encoded it at full size, and at 273 KB when we also resized it to 1600 pixels wide. Same settings, a tenth of the bytes.

The direct wayImageMagickmacOS · Linux · Windows

Resize to 1600 pixels wide and save a JPEG at quality 82, without the camera's metadata:

magick photo.jpg -resize 1600x -quality 82 +profile '!icc,*' photo-1600.jpg

1600x sets the width and lets the height follow. +profile '!icc,*' removes everything except the colour profile. Install it with brew install imagemagick on a Mac or apt install imagemagick on Debian and Ubuntu.

Work out the size first

Open the page, right-click the image and choose Inspect. In Chrome's Elements panel, hovering over the image's src address shows its rendered size (how big it is on the page, in CSS pixels) and its intrinsic size (how big the file is).

Make the file twice the rendered width, and no more. A high-density screen packs two or three device pixels into each CSS pixel, so an image shown 800 pixels wide needs 1600 to look sharp. Beyond twice, the extra pixels cost bytes nobody can see. How to resize images has the sizes that cover most layouts, and the aspect-ratio arithmetic.

Keep the colour profile

-strip is the usual advice, and it removes the colour profile along with the camera data. On an sRGB image that changes nothing. The test photo here is in Adobe RGB, as camera exports often are (phone photos are often Display P3), and stripped, its colours go flat. So does cwebp by default: add -metadata icc.

Then pick the format

We took a public-domain photo of the Tetons from a Canon EOS 7D, resized it to 1600 × 1067, encoded it with each encoder and scored the results with SSIMULACRA 2, a metric built to track what people see. Its authors put 70 at "high quality", where artefacts are barely noticeable side by side, and 80 at "very high quality", where they can't be seen side by side at all. Higher is better.

Photo, 1600 × 1067 Size Score
Original, 5184 × 3456 11.1 MB
JPEG, quality 82 273 KB 81.3
JPEG, quality 70 189 KB 74.4
WebP, quality 90 241 KB 81.2
WebP, quality 80 138 KB 71.4
AVIF, quality 75 185 KB 80.3
AVIF, quality 60 119 KB 73.1

Read the table in pairs of similar scores. At about 81, AVIF is a third smaller than JPEG and WebP only 12% smaller. At about 73, AVIF is 37% smaller than JPEG. WebP's quality number is not JPEG's: WebP 80 is half the size of JPEG 82, but it scores ten points lower.

A flat illustration behaves differently. The 3000 × 2000 mountain sunset we use for our screenshots, resized to the same 1600 pixels:

Illustration, 1600 × 1067 Size Score
JPEG, quality 82 55.9 KB 84.3
WebP, quality 90 25.8 KB 83.1
AVIF, quality 60 6.8 KB 84.9

Same score, an eighth of the size. Smooth gradients and hard edges are what AVIF is best at, and what JPEG is worst at.

The direct waycwebp · avifencmacOS · Linux · Windows

Resize once to a lossless PNG, then encode it each way:

magick photo.jpg -resize 1600x +profile '!icc,*' photo-1600.png
cwebp -q 90 -metadata icc photo-1600.png -o photo-1600.webp
avifenc -q 60 photo-1600.png photo-1600.avif

avifenc comes from libavif: brew install webp libavif, or apt install webp libavif-bin. Start AVIF at quality 60 and WebP at 90, and lower them while you can't see a difference on the most detailed image you have.

Every current major browser shows WebP and AVIF. The HTML below keeps a JPEG for anything that doesn't.

Already on a Mac: sips

sips is built into macOS and resizes with -Z, which fits the long edge. On macOS 26.5 it also writes AVIF:

sips -Z 1600 -s format avif photo.jpg --out photo-1600.avif

That gave 203 KB and a score of 83.6 on the test photo. Its quality scale is its own: -s formatOptions 82 on a JPEG gave 350 KB, scoring 88.4, much larger than ImageMagick's quality 82. sips also keeps the camera metadata (make, model and the rest), so it isn't the tool for removing a photo's location.

Serve the right file to each screen

One file for every screen means phones download the desktop image. srcset lists the widths you made, sizes tells the browser how wide the image will be shown, and the browser picks the smallest file that is sharp enough:

<picture>
  <source type="image/avif"
          srcset="photo-800.avif 800w, photo-1600.avif 1600w"
          sizes="(max-width: 840px) 100vw, 800px">
  <img src="photo-1600.jpg"
       srcset="photo-800.jpg 800w, photo-1600.jpg 1600w"
       sizes="(max-width: 840px) 100vw, 800px"
       width="1600" height="1067"
       alt="The Teton Range under snow, lit by the low sun"
       loading="lazy" decoding="async">
</picture>

Here the image fills the screen below 840 pixels and sits in an 800-pixel column above it. width and height are the file's own size: the browser uses them to reserve the right space before the image loads, so the text below it doesn't jump. Your CSS can still scale it (img { max-width: 100%; height: auto; }).

Don't lazy-load the first image

loading="lazy" belongs on images below the first screen. The big image at the top is usually what the browser counts as the page having loaded (Largest Contentful Paint), and lazy-loading it delays exactly that. Leave it off there, or use fetchpriority="high" instead. web.dev has the details.

Make the set in the browser

The Image Resizer exports several widths in several formats at once, which is the set srcset wants.

The Image Resizer with the landscape photo loaded: in the Export panel the Queue lists 800w and 1600w, the JPEG and WebP format chips are on, and the button reads Export 4 files

Two widths times two formats: four files, in one ZIP.

  1. Open Image Resizer and drop the image in.
  2. In Export, open Custom and type 800w under Shorthand, then Add. Do the same for 1600w.
  3. Under Formats, turn off PNG and turn on JPEG and WebP. Each gets its own quality slider: JPEG starts at 85, WebP at 90.
  4. Press Export 4 files. You get a ZIP with names like photo-800w.webp and photo-1600w.jpg, ready for srcset.

For a folder of images all going to one size, Compress Image is quicker: drop them in, set Max dimension to the width you need (1600 px for an 800-pixel column on a sharp screen), and switch on Convert to WebP. Remove metadata is on by default. The presets map to quality 85 (High quality), 75 (Balanced) and 55 (Smallest). It uses your browser's own encoder, so its sizes won't match the tables above exactly. If a file would come out larger, you keep the original, marked Already optimized: the illustration above, re-encoded at full size at quality 82, grew from 115 KB to 118 KB, which is what that rule is for.

AVIF from the browser tools

The browser tools here make JPEG and WebP reliably. The Image Converter lists AVIF, but it uses the browser's encoder, and where the browser can't encode AVIF the file can come out as a PNG with an .avif name. For AVIF, use avifenc or sips above. Compress Image only writes AVIF for an AVIF you gave it, and falls back to WebP when the browser can't.

Picking the format itself is covered in How to convert between image formats. When you're done, reload the page with the Network panel open and filter by Img: the sizes in that column are what your visitors download.

Questions people ask

How big should an image on a web page be, in kilobytes?

There is no single number, because a flat illustration and a detailed photo compress very differently. In our test a 1600-pixel-wide photo came out at 119 KB as AVIF and 189 KB as JPEG at the same quality, while a flat illustration of the same width was under 7 KB as AVIF. Get the pixel size right first, then let the quality setting decide the bytes.

Is WebP always smaller than JPEG?

Not at the same quality. On the photo we measured, WebP at quality 90 was only 12% smaller than JPEG at 82, for the same score. WebP at 80 is much smaller, but it is also visibly softer. On flat graphics WebP is less than half the size of JPEG. AVIF beat both on both images we tried.

Should I lazy-load every image?

No. Lazy-load the images below the first screen. The large image at the top of the page is usually what the browser measures as the page having loaded, and lazy-loading it makes that later, not sooner.

Why did my photo's colours go flat after optimising it?

The colour profile was stripped. A camera or phone photo is often in Adobe RGB or Display P3, and without its profile the browser reads the numbers as sRGB, which looks duller. Strip the camera metadata but keep the ICC profile, as the commands in this guide do.

Do I still need width and height if I set the size in CSS?

Yes. The browser uses the two attributes to reserve the right space before the image arrives, so the text doesn't jump when it loads. CSS can still scale the image; the attributes only give it its shape.

Tools in this guide

Everything runs on your device

All guides

/
123 items
Runs in your browser·Your files stay on this device
Out0 B
Ready—