Getting an image ready to publish
Resize to the size the image will actually be displayed, at most double that for high density screens. Crop to the shape the layout needs rather than letting the browser squash it. Compress until artefacts just appear, then step back one notch. Strip the metadata last. The order matters: every step after the first works on far fewer pixels.
Dimensions come first
Pixel count grows with the square of the width, so a modest difference in dimensions is an enormous difference in data. An image stored at 4000 pixels wide and shown in an 800 pixel column carries about twenty five times the data it needs, and no quality setting recovers that.
| Stored size | Pixels | Data relative to 800px |
|---|---|---|
| 4000 x 2667 | 10.7 million | 25x |
| 1600 x 1067 | 1.7 million | 4x |
| 800 x 533 | 0.43 million | 1x |
To pick a target width, measure the widest the image is ever rendered in the layout, not the widest the screen gets. A card in a three column grid may only ever be 380 pixels wide. If one file serves several places, size it for the largest.
Device pixels, CSS pixels and the DPI myth
A CSS pixel is a unit of layout, not a physical dot. Device pixel ratio is how many device pixels the screen paints per CSS pixel: 1 on older monitors, 2 on most modern phones and laptops, 3 on some phones. An 800 CSS pixel column at ratio 2 is painted with 1600 device pixels, which is why an image sized to its CSS width looks soft.
The practical rule is 2x. Export at twice the displayed width and let the browser scale down. Going to 3x costs another 125% in data for a difference few people see at normal viewing distance.
DPI and PPI stored in a file are irrelevant to the web. They are one header number saying what physical size the file should print at, and browsers ignore it entirely.
printed width in inches = pixel width / PPI
3000 px / 300 ppi = 10.0 in
3000 px / 72 ppi = 41.7 in same file, same 3000 pixels
Exporting at "300 DPI" adds no pixels and changes no image data.
What resampling does
Scaling down means many source pixels become one. Detail finer than the new grid cannot be represented, and if the resampler samples too few source pixels instead of averaging across the whole area, that detail folds back as false patterning: jagged diagonals, and moire on fine repeating textures such as a striped shirt or a table with one pixel borders. A good downscale averages every contributing pixel, and usually needs a little sharpening after.
Scaling up creates no detail. Interpolation only guesses at values between pixels that already exist, so the result is soft or blocky. Machine learning upscalers invent plausible detail instead, which is not the same as recovering it.
| Filter | How it works | Result |
|---|---|---|
| Nearest neighbour | Copies the closest source pixel | No blending. Right for pixel art and integer scales, jagged otherwise |
| Bilinear | Averages the four surrounding pixels | Fast and soft, loses detail on large reductions |
| Lanczos | Windowed sinc over a wider neighbourhood | Sharpest downscale, halos on extreme contrast edges |
Aspect ratio: crop, letterbox or stretch
Cropping keeps the subject at its proper scale and discards the edges, and is the right default. Letterboxing keeps the whole frame but adds bars and forces a choice of bar colour; it earns its place when nothing may be cut, as with artwork or a diagram. Stretching distorts, and the eye catches that instantly on faces, circles and type.
.tile img {
width: 100%;
height: 100%;
object-fit: cover; /* crop; contain = letterbox, fill = stretch */
}
When one file appears in several shapes, think in terms of the safe area: the region that survives every crop. A 16:9 banner cuts top and bottom, a 1:1 tile and a 4:5 card cut the sides, so what all of them keep is a band through the centre. Keep the subject and any text inside it, or a face near the edge of a landscape photo gets beheaded by the square crop.
Finding the quality setting
A quality number is not a percentage of anything, and the scales are not comparable between encoders. JPEG 80, WebP 80 and AVIF 80 are three unrelated settings.
The method is the same for all of them. Export at a few settings, view the result at the size it will be shown, and check where artefacts surface first: smooth gradients such as skies, which band and blotch; hard edges and text, which ring. Find where the damage becomes visible, step back one notch, stop.
One fixed number is wrong for every image because the content decides how much can be thrown away: a noisy, textured photograph needs more bits to survive, while a flat illustration falls apart at a setting a busy photo shrugs off.
| Content | Starting point |
|---|---|
| Photograph at display size | JPEG 78 to 85, WebP 75 to 82, AVIF 50 to 62 |
| Photograph at 2x | Five to ten points lower |
| Screenshot, flat graphic, text | Lossless, or lossy at 90 and above |
Cutouts, soft edges and halos
Removing the background is right when the image must sit on more than one background colour, or overlap other elements: product shots, logos, a person composited into a layout. It is wrong where the boundary is genuinely fine, as with hair, foliage or glass, because a bad matte looks worse than an honest rectangle.
A hard edge is binary, every pixel fully opaque or fully transparent, which suits flat graphics but stair steps on anything photographic. A soft matte allows fractional opacity, so a pixel can be 40% subject, which is the only way hair looks right.
The halo comes from the boundary pixels. Lens blur and antialiasing already mixed subject colour with the old background, so each holds:
observed = alpha * foreground + (1 - alpha) * background
Background removal computes alpha only. The colour left in those pixels is still contaminated, so a subject cut from a white studio shot carries a pale fringe: invisible on a white page, obvious on a dark one. Proper matting solves for the foreground colour too, exposed as defringe or decontaminate colours. Failing that, choke the matte inwards by a fraction of a pixel and re-feather it.
Rotation and metadata
An image upright in one program and sideways in another is almost always EXIF orientation. Cameras store the sensor image unrotated and add a tag saying how to turn it. Software that reads the tag shows it correctly; software that ignores it, including many image libraries and thumbnailers, shows the raw pixels on their side.
| Orientation | Meaning |
|---|---|
| 1 | Stored the right way up |
| 3 | Rotate 180 degrees |
| 6 | Rotate 90 degrees clockwise |
| 8 | Rotate 90 degrees anticlockwise |
| 2, 4, 5, 7 | Mirrored variants |
The fix is to bake the rotation into the pixels and set the tag to 1 or remove it. Rotating in 90 degree steps rearranges pixels without resampling them. Watch for the double rotation: pixels already turned, tag still set, so every compliant viewer turns them again.
Stripping metadata is a privacy step, not housekeeping. EXIF, IPTC and XMP blocks routinely carry GPS coordinates accurate to a few metres, capture time, camera make, model and serial number, owner name, and sometimes an embedded thumbnail still showing the image before it was cropped. A photo taken at home and posted intact publishes a home address.
Strip it last, with one exception: the ICC colour profile sits alongside that metadata, and removing it from a wide gamut image leaves numbers that get read as sRGB, showing up as flat or oversaturated colour. Convert to sRGB first, then strip everything else.