
WebP vs AVIF: which format wins, and where
Measured compression figures with sources, WebP's 8-bit and 4:2:0 ceilings, AVIF's encode cost and missing progressive rendering, and how to choose per content type.

Quality 80 is not 80% of anything, it is a scale factor on a quantisation table. Finding the point where loss stops being visible takes measurement, not a setting copied from another project.
A JPEG encoder's quality setting is not a percentage of anything. The encoder splits the image into 8 × 8 blocks, converts each block into frequency coefficients, then divides those coefficients by entries in a quantisation table and rounds. The quality value scales that table. Nothing in the pipeline promises that quality 80 in one encoder produces the same table, or the same visual result, as quality 80 in another, and the same encoder at 80 behaves differently again once you change chroma subsampling.
So the number you settled on for one project does not transfer to the next. The method transfers. Four steps, in this order: get the pixel dimensions right, remove the bytes that are not pixels, pick subsampling from the content, then find the quality knee by measuring instead of squinting.
A photo straight off a recent phone is roughly 4032 × 3024, which is 12.19 megapixels. If your content column displays it at 1200 × 900, you need 1.08 megapixels, so you are compressing about eleven times more data than the page can show. Serve a 2x asset for dense displays and it is 2400 × 1800, or 4.32 megapixels, still nearly three times more than the layout needs at 1x.
No quality slider gives you an 11x reduction without visible damage, and resizing costs you nothing visible at all, because the pixels were never going to be displayed. Start every job with resize, and use crop where the composition allows it. Tuning the encoder before the dimensions are right is optimising the wrong variable.
A camera JPEG carries more than an image. There are EXIF blocks, GPS coordinates, maker notes, sometimes an XMP packet, and almost always an embedded preview. That preview is itself a complete JPEG, and depending on the camera it ranges from a few kilobytes to a few hundred. None of it is needed on a web page, and the EXIF remover clears the lot in one pass. It is also the privacy-safe default, since location data in a product photo is a real leak.
One exception: the ICC colour profile. Dropping it from an sRGB image is harmless. Dropping it from a Display P3 photo is not, because browsers treat an untagged image as sRGB and the saturated reds and greens shift visibly. The fix is not to keep a large profile around but to convert the image to sRGB first, then strip.
Human vision resolves brightness detail far better than colour detail, and every lossy codec exploits that. At 4:4:4 each pixel gets three samples: Y, Cb and Cr. At 4:2:0 a 2 × 2 block keeps four luma samples but only one Cb and one Cr, so six samples replace twelve. Half the data disappears before compression proper even starts.
On photographs that is nearly free. It stops being free on red or blue text over white, thin coloured rules, hard-edged logos and interface screenshots, where the colour edge smears across the block. For that kind of content, switching to 4:4:4 and accepting a lower quality number produces a better result than keeping 4:2:0 at a higher one. Worth knowing: lossy WebP has no 4:4:4 mode at all, which is one of several format ceilings covered in WebP vs AVIF.
"Looks fine to me" does not scale. It depends on your monitor, your zoom level and how carefully you were looking that afternoon. Perceptual metrics give you a repeatable number instead. Butteraugli, and SSIMULACRA 2 which builds on the same ideas, weight the difference between two images by how sensitive human vision is to that kind of error.
SSIMULACRA 2 is particularly useful because its documentation anchors scores to concrete encoder settings:
For the web, 70 to 85 is a sensible working band: around 85 for hero and product imagery, around 70 for thumbnails in a grid. Keep archive and pre-press copies at 90 or above.
Pick five images that represent your catalogue, encode each at 95, 90, 85, 80, 75 and 70, and write the file sizes into a table. The shape is almost always the same: the curve is steep at the top. Going from 95 to 90 cuts a lot of bytes and leaves no visible trace. Going from 75 to 70 saves comparatively little and visibly increases artifacts. The knee usually sits between 80 and 85, but it moves with content, which is exactly why one global setting underserves half your images. The image compressor is a quick way to produce that ladder and compare outputs side by side.
When you inspect a candidate, do not scan around randomly. Degradation appears in the same four places every time. Go straight to them, at 100% zoom, on the device you actually ship to.
An 8-bit channel only has 256 steps to describe a gradient. Quantisation merges some of those steps and the transition breaks into visible stripes. The counterintuitive fix is to add a very small amount of noise or dither before encoding: the randomness scatters the step boundaries and the stripes stop reading as stripes. It costs a few kilobytes and solves the problem more cheaply than raising quality across the whole image.
Opening a lossy file and saving it again causes generation loss, but the detail matters. Re-saving with the same encoder, the same settings and the same pixel dimensions is surprisingly stable, because the signal already sits on that quantisation grid. Change the dimensions by even one pixel, or rotate the image, and the 8 × 8 block grid shifts underneath the content: every block is re-quantised against new neighbours, and damage accumulates fast.
The rule that follows is simple. Always derive deliverables from the untouched master, never from a file you already shipped. Raising quality on a second pass does not recover anything; it just stores the existing artifacts more faithfully in a bigger file. The same applies across formats: converting a JPEG to AVIF also encodes the JPEG's artifacts, so the saving is smaller than converting from the original would have been.
PNG is lossless, so compressing one means one of two distinct operations. The first is filter selection and deflate optimisation: pixels stay bit-for-bit identical, the gain is modest, and there is no risk. The second is palette quantisation, reducing the image to 256 colours. That is genuinely lossy, but on icons, interface graphics and flat illustration it is usually indistinguishable while cutting the file dramatically.
Photographs should not be PNG in the first place. Move them to a lossy format, or to a modern format with alpha if you need transparency; PNG to WebP lets you try both lossy and lossless and keep whichever wins.
There is no encoder-independent number, but the SSIMULACRA 2 scale gives a good anchor: score 70, roughly libjpeg-turbo 4:2:0 quality 70, is the level where someone who has not seen the original notices nothing, while score 90, roughly 4:4:4 quality 95, counts as visually lossless. Aim for 70-85 on the web and 90 or above for archives.
Re-saving with the same encoder, settings and pixel dimensions is fairly stable because the signal already sits on that quantisation grid. Change the size or rotate the image and the 8 x 8 block grid shifts, so each save adds fresh artifacts. Always generate from the master instead.
It does not touch pixels, only metadata and the embedded preview. The one thing to watch is the ICC profile: removing it from a Display P3 image makes browsers treat it as sRGB and the colours shift. Convert to sRGB first, then strip.
Banding comes from quantisation merging steps in an 8-bit gradient that only has 256 of them. Raising quality everywhere is an expensive fix. Adding a very small amount of noise or dither before encoding scatters the step boundaries and costs a few kilobytes.
It depends which operation you mean. Filter and deflate optimisation is fully lossless and leaves pixels bit-for-bit identical. Palette quantisation to 256 colours is lossy, though on interface graphics and flat illustration the difference is usually invisible.

Measured compression figures with sources, WebP's 8-bit and 4:2:0 ceilings, AVIF's encode cost and missing progressive rendering, and how to choose per content type.

What removing an AI badge actually involves, when inpainting gives a clean result, and why erasing the visible mark leaves the embedded provenance intact.