JPEG, PNG, WebP or AVIF? Picking Image Formats and Compression Settings That Actually Work
Which image format to use for photos, screenshots and logos, sensible quality settings, why resizing matters more than the format, and measured results from compressing a real UI screenshot.
Images are usually the heaviest part of a web page. On many sites they are also the easiest performance win: the same picture can often be served at a third of its size, and nobody notices the difference. The hard part is knowing which knob to turn. Should you change the format, lower the quality, or resize? This article answers that with simple rules and a small experiment you can reproduce.
The four formats in one table
| Format | Compression | Transparency | Best for | Browser support |
|---|---|---|---|---|
| JPEG | Lossy | No | Photos, when nothing else is possible | Everywhere |
| PNG | Lossless | Yes | Screenshots, UI, diagrams, images with text | Everywhere |
| WebP | Lossy or lossless | Yes | Almost everything, a safe modern default | All current browsers (Safari since version 14) |
| AVIF | Lossy or lossless | Yes | Photos and large hero images, when you can encode it | Chrome, Firefox, Safari 16+, Edge 121+ |
Two formats are missing on purpose. SVG is the right choice for logos, icons and simple illustrations because it is vector-based and stays sharp at any size. GIF should be replaced: a short looping video (MP4 or WebM) or an animated WebP is usually many times smaller.
Lossy vs lossless: the decision that matters most
Lossless formats (PNG, lossless WebP) store every pixel exactly. They compress well when an image has large areas of identical color, such as a code editor, a dashboard or a diagram.
Lossy formats (JPEG, lossy WebP, AVIF) throw away detail the eye is unlikely to notice. They are excellent for photos, which are full of noise and smooth gradients. They are poor at sharp edges: around text, a lossy encoder produces faint blocks and halos (known as "ringing").
So the first question is not "which format", but "is this a photo or a graphic?"
- Photo, render or anything with natural texture → lossy.
- Screenshot, chart, UI mockup, image with small text → lossless first, then try lossy WebP or AVIF and check the text by eye.
An experiment with a real screenshot
To check these rules, I took a screenshot of a nicetool.dev page at 2× pixel density (2560×1600 pixels, as a Retina laptop would capture it) and encoded it in several ways with sharp, the same libvips-based library many image CDNs use:
| Version | Size | Saving |
|---|---|---|
| Original screenshot from the browser (PNG) | 253 KB | - |
| PNG, maximum compression | 95 KB | 62% |
| WebP lossless | 98 KB | 61% |
| JPEG, quality 80 | 151 KB | 40% |
| WebP, quality 80 | 101 KB | 60% |
| AVIF, quality 50 | 64 KB | 75% |
| PNG, resized to 1280 px wide | 158 KB | 38% |
| WebP quality 80, resized to 1280 px wide | 41 KB | 84% |
The results hold a few surprises:
- Re-saving the PNG alone saved 62%. Screenshot tools and browsers write PNGs quickly, not compactly. A pass through an optimizer costs nothing in quality.
- JPEG was the worst lossy option, larger than the lossless PNG and with visible artifacts around text. For screenshots, JPEG is simply the wrong tool.
- Downscaling made the PNG bigger. Resizing blends neighboring pixels, which creates thousands of new in-between colors along every edge, and lossless compression handles those badly. The same resized image as lossy WebP was the smallest of all.
- AVIF was the smallest at full resolution, about a third smaller than WebP.
These numbers are for one screenshot. A busier screenshot or a photo will give different values, but the ranking is typical. For photos, Google's own comparison found lossy WebP to be 25-34% smaller than JPEG at similar quality, and lossless WebP about 26% smaller than PNG. AVIF usually goes further, especially at lower quality settings.
Resize before you compress
The biggest saving almost never comes from the format. It comes from not shipping pixels nobody sees. A 4000×3000 photo from a phone displayed in an 800-pixel-wide column carries about 25 times more pixels than needed (about 6 times on a 2× screen).
Practical rules:
- Find the largest size the image is actually displayed at, multiply by 2 for high-density screens, and resize to that. For a typical blog column, 1600 pixels wide is plenty.
- Use
srcsetandsizesso phones download a smaller file than desktops:
<img
src="hero-1600.webp"
srcset="hero-800.webp 800w, hero-1600.webp 1600w"
sizes="(min-width: 960px) 800px, 100vw"
width="1600" height="900"
alt="Dashboard overview">
- Always set
widthandheight(or CSSaspect-ratio). The browser can then reserve space before the image loads, which prevents layout shift. - Add
loading="lazy"to images below the fold, but not to the main image at the top of the page (your LCP element). Give that onefetchpriority="high"instead.
Quality settings that work
Quality numbers are not comparable between formats. "80" in JPEG does not mean the same as "80" in AVIF. Good starting points:
| Format | Start at | Notes |
|---|---|---|
| JPEG | 75-85 | Above 90 the file grows quickly with little visible gain |
| WebP | 75-80 | Check text and fine lines in screenshots |
| AVIF | 45-60 | AVIF holds up well at numbers that would look bad in JPEG |
Then look at the result at 100% zoom, on the kind of screen your users have. Pay attention to faces, skin, sky gradients (banding) and small text. If you see no difference, try 5-10 points lower.
Two more habits help:
- Keep the originals. Every lossy re-encode loses a bit more detail ("generation loss"). Always compress from the original, never from an already compressed copy.
- Strip metadata. Photos from phones carry EXIF data, which can include the GPS location where the picture was taken. Most optimizers remove it, which saves a few kilobytes and protects your privacy.
Serving modern formats with a fallback
All current browsers support WebP, so for most sites WebP alone is enough. If you also want AVIF for its extra savings, use <picture> so each browser picks the best format it understands:
<picture>
<source srcset="photo.avif" type="image/avif">
<source srcset="photo.webp" type="image/webp">
<img src="photo.jpg" width="1200" height="800" alt="Team photo">
</picture>
Frameworks such as Next.js (next/image) and most image CDNs do this automatically, based on the Accept header the browser sends. If you already use one, check that AVIF is enabled in its configuration, because it is often off by default due to slower encoding.
A quick decision guide
- Logo or icon → SVG.
- Photo → resize, then WebP at 75-80 (or AVIF at 45-60), with JPEG only as a fallback.
- Screenshot or diagram → optimized PNG or lossless WebP; try lossy WebP or AVIF and check the text.
- Needs transparency → PNG, WebP or AVIF, never JPEG.
- Animation → MP4/WebM video or animated WebP instead of GIF.
For one-off images, you do not need a build pipeline. The Image Compressor on nicetool.dev resizes and converts JPEG, PNG and WebP (and AVIF where your browser can encode it) right in your browser. Your files are never uploaded, metadata is removed, and you can compare the before and after size of each image before downloading.
Written by
Nguyễn Thành Nam
Full-Stack Engineer · Backend & Platform
Full-stack engineer with 9+ years of experience building high-traffic APIs and platforms with Go, NestJS, PHP (Laravel, Phalcon) and Node.js. Specializes in GraphQL API design, real-time systems and performance optimization, and builds NICETOOL.dev for the developer community.