Images
How to shrink images for the web without visible quality loss
Most oversized web images are oversized in pixels, not in quality. This guide puts the steps in the order that pays back most: match the pixel dimensions to the size and density of the slot the image fills, then set the quality, then choose the format, then remove metadata, then let the browser pick among sizes and defer images that are offscreen. It ends with how to check each step, including the behaviors in this site's tools that can trip you up.
By the MaffeiTools team · Updated · 8 min read
Pixels first: a photo costs memory by its dimensions, not its file format
The file size is what travels over the network. Once it arrives, the browser decodes the image into a grid of pixels, and that grid costs the same whether the file was a JPEG, a WebP or a PNG: width times height times four bytes for red, green, blue and alpha. A 4000 by 3000 phone photo is 12,000,000 pixels and 48,000,000 bytes of decoded memory. A quality slider changes the bytes sent; only resizing shrinks the decoded image too.
So the first move is to cap the pixel dimensions at what the page can actually show. The block below applies the Image Optimizer's rule, height = round(height x max width / width), to that 4000 by 3000 source.
source 4000x3000: 12000000 px, 48000000 bytes decoded (RGBA) slot 800 @1x: max width 800 -> 800x600, 480000 px (96.0% fewer), 1920000 bytes decoded slot 800 @2x: max width 1600 -> 1600x1200, 1920000 px (84.0% fewer), 7680000 bytes decoded slot 800 @3x: max width 2400 -> 2400x1800, 4320000 px (64.0% fewer), 17280000 bytes decoded
Density: how many device pixels a CSS pixel needs
An 800 CSS pixel slot is 800 device pixels on a standard display and 1600 on a display with two device pixels per CSS pixel. MDN's responsive images guide describes this as the case where high-resolution screens need larger images than you might expect. Chrome's Lighthouse audit for oversized images compares the rendered size, including device pixel ratio, with the actual file dimensions and fails an image when its rendered size is at least 4 KiB smaller than its actual size; in Lighthouse 13 that audit moved into the Improve image delivery insight.
The numbers above show why the choice of density matters. Each step multiplies pixels by the square of the scale: the 2x image has four times the pixels of the 1x one, and 3x has 2.25 times the pixels of 2x. Serve the densities your audience actually has, and add 3x only where the extra sharpness on those devices is worth that cost.
The tools differ in how they resize. The compressor's Max width field defaults to 1920 and accepts 100 to 8192. It is passed to the compression library as a limit on the longer side, so a portrait image is capped by its height, and it only ever shrinks. The Image Optimizer offers 3840, 1920, 1280, 800 and 400, caps the width, and also never enlarges. The Image Resizer takes exact dimensions up to 8192 and will happily upscale, which adds bytes and no detail.
Quality settings and where they stop paying
Browsers export lossy images from a canvas with a quality value between 0 and 1. MDN's toBlob reference says it applies to formats that support lossy compression, such as JPEG and WebP, and that a value outside the range falls back to the browser's default. PNG is lossless, so the slider means nothing for it; the Image Optimizer hides the control when PNG is selected.
The starting points in this site's tools are 80 in the compressor and the Image Optimizer, 85 in the format converters that target JPEG, WebP or AVIF, and 92 in the Image Resizer. Those are defaults, not standards. The number is also not a shared unit: 80 in a JPEG encoder, a WebP encoder and an AVIF encoder maps to different amounts of quantization, so compare bytes and appearance rather than the setting.
A workable procedure is to encode at the default, zoom to 100 percent, and look where compression fails first: smooth gradients such as sky show blocking or banding, edges next to text grow halos, and fine texture turns to smear. Lower the setting in steps of 5 until one of those appears, then go back one step. To test the top end, encode at the maximum as well. If that file is far larger and the two look identical at 100 percent, the extra bytes are buying nothing.
Worth knowing. The compressor uses the browser-image-compression library (version 2.0.2 here). It encodes once at your quality; if that result is larger than the original file, it retries up to 10 times, multiplying quality by 0.95 each round (0.85 for PNG, where canvas ignores quality anyway) and returns the last attempt even if it is still bigger. Recompressing a file that was already well optimized can therefore produce a larger file. The result card shows the size, and the green saving badge appears only when the file got smaller.
WebP or AVIF instead of JPEG
MDN's format guide puts lossy WebP at 25 to 35 percent smaller than JPEG at similar visual quality on average, and gives around 50 percent smaller as an example for AVIF. Both figures are averages from comparisons, not promises for a given image. The trade-offs are support and speed. WebP works in all current major browsers, with Safari on macOS needing version 14 or later. AVIF reached Firefox and Safari a year or more after Chrome, so older browsers still in use will not display it, and it cannot render progressively, so a large AVIF must finish downloading before it shows.
That is why MDN recommends a picture element: a source with type image/avif, one with image/webp, and an img with the JPEG or PNG fallback, typically two or three candidates in total. The browser skips any source whose type it cannot decode and uses the img as the fallback.
The converters produce these formats in the browser: png-to-webp, jpg-to-webp and jpg-to-avif, each defaulting to a quality of 85. The AVIF path runs a WebAssembly encoder at speed 8 on a 0 to 10 scale, chosen in the code to trade a small size penalty for a large speedup, so a slower encoder setting elsewhere can squeeze out a little more. Convert from the original file when you have it. Converting a JPEG to WebP re-encodes pixels that are already degraded, and the losses stack.
Metadata: a privacy step first, a size step second
Camera files carry Exif metadata: the device, the lens settings, the capture time, and GPS coordinates if location was on. The EXIF Reader tool shows exactly what a file holds, flags when GPS coordinates are present, and warns that the data can be sensitive. Reading is all it does; it does not rewrite the file.
Stripping usually happens as a side effect of resizing. The Image Resizer, Image Optimizer and Image Crop draw the pixels onto a canvas and export from there, and a canvas export carries no Exif block, so there is nothing to opt out of. The compressor has a Preserve EXIF switch that is off by default. Even when it is on, the library copies the Exif block only for a JPEG that stays a JPEG, and it resets the Orientation tag to 1 in the copy.
For size, the pixel data in most photos dwarfs the metadata, so removing metadata rarely moves the file as much as resizing does. Treat it as the step that keeps home coordinates out of a public post, and verify it by opening the output in the EXIF Reader.
Responsive images: let the browser choose
For an image whose display size changes with the layout, provide several files in srcset with width descriptors and describe the slot in sizes. MDN's example offers a 480 pixel and an 800 pixel wide file, with a sizes value that gives 480px when the viewport is at most 600px and 800px otherwise. The browser weighs screen size, pixel density, zoom and network speed, uses the first sizes condition that matches, and picks the first srcset entry at least as wide as the slot. In MDN's demonstration the 800 pixel file was 128 KB and the 480 pixel file 63 KB. Slot widths in sizes take length units such as px or vw, not percentages.
For an image shown at a fixed CSS size, skip sizes and use density descriptors: srcset with a 320 pixel file, a 480 pixel file marked 1.5x and a 640 pixel file marked 2x. When narrow screens need a different crop rather than a scaled copy, use picture with media conditions. The Image Crop tool can make those crops, but it exports PNG, which is lossless and large for photographs, so run the result through the compressor or a converter afterward.
Set width and height attributes on the img to the intrinsic size of the largest srcset file. MDN explains that this lets the browser reserve the space from the aspect ratio before the file arrives, which reduces layout shift.
Lazy loading, and the images that must not be lazy
Adding loading=lazy to an img defers the download until the image is near the viewport. MDN lists support from Chrome 77, Firefox 75 and Safari 15.4, and notes that deferral only happens when JavaScript is enabled. It saves the bytes of images a visitor never scrolls to. It does not make any file smaller.
web.dev's guidance is explicit that images likely to be in the first viewport, and especially the largest contentful paint image, should keep the default eager loading, because lazy loading delays them. Explicit width and height matter even more for lazy images, since an unloaded image has zero size and the page shifts when it arrives.
Checking the result instead of trusting a slider
Every one of the steps above can be verified in a minute:
- Compare the byte size in the tool's result card with the original, and expect the resize step to account for most of the saving.
- Inspect at 100 percent zoom, and on a high-density screen if you serve 2x files. Look at gradients, text edges and skin tones.
- Open the browser network panel with the cache disabled, as MDN suggests, to see which srcset candidate was requested and how many bytes were transferred.
- Run a Lighthouse audit for oversized images or the Improve image delivery insight.
- Open the output in the EXIF Reader and confirm no location block remains.
Worth knowing. Three behaviors to know. The Image Resizer fills the canvas with white for WebP and JPEG output, so transparency survives only with PNG selected. The Image Crop tool always exports PNG. All of these tools work through a canvas, which produces a still image, so an animated GIF will not stay animated.