How to compress images for a faster website
Images are usually the heaviest thing on a page and the easiest to fix. This is the workflow in the order that saves the most bytes, with real numbers from a worked example.
Why images dominate page weight
On a typical content site, images account for the majority of bytes transferred, usually more than HTML, CSS and JavaScript combined. They also normally determine Largest Contentful Paint, the Core Web Vitals metric measuring when the biggest visible element finishes rendering. On most pages that element is an image.
The good news is that image weight is unusually tractable. Unlike JavaScript, where cutting bytes means removing features, you can normally cut 80% of image weight with no perceptible change to the page. It is the rare optimisation with no trade-off.
The order below matters. Each step is listed by how much it typically saves, so if you stop after step two you will still have captured most of the benefit.
Step 1: Audit what you ship
Before changing anything, find out what is actually being served. Open your page, press F12, go to the Network tab, filter to Img, and reload with caching disabled.
Sort by size, largest first, and look for three things:
- Any image over 200 KB. On a content page this is almost always fixable.
- Intrinsic size far larger than display size. Hovering an image in the Network panel shows both its natural dimensions and its rendered dimensions. A 4000 px file in a 600 px slot is pure waste.
- PNGs that are photographs. These are usually the largest files on the page.
Write down the total. You will want it for comparison, and the number is usually more alarming than people expect.
Step 2: Resize (the biggest win)
File size scales roughly with pixel count, so halving both dimensions removes about 75% of the data. No compression setting comes close, and unlike compression it costs no visible quality at all, provided the image is still at least as large as it is displayed.
The rule for high-density screens: serve about twice the CSS display width, and no more. Beyond 2× the extra pixels are invisible even on the sharpest phone display.
| Where it appears | Typical CSS width | Export at |
|---|---|---|
| Full-width hero | ~1000 px | 1600-2000 px |
| In-article image | ~600 px | 1000-1200 px |
| Card / grid thumbnail | ~300 px | 600 px |
| Avatar | ~48 px | 96-128 px |
| Header logo | ~150 px | SVG, or 300 px PNG |
Our image resizer handles this in batches, and downscales in steps rather than one jump so edges stay sharp instead of aliased.
Step 3: Convert the format
With dimensions sorted, the format change is the next largest lever. In practice this means one rule: convert to WebP.
Expect roughly 25-35% off a photographic JPEG, and 50-80% off a transparent PNG. The PNG case is the dramatic one and the one most sites overlook, because UI graphics and logos feel small individually but add up.
Keep the originals. You are producing delivery copies, not replacing masters.
Step 4: Compress
Only now does the quality slider earn its place. Applied to an image that is already the right size and format, quality 80 is close to free; applied to a 4000 px PNG it is rearranging deck chairs.
- Photographs: quality 78-85.
- Images containing text or sharp edges: 88-92, or keep them lossless.
- Thumbnails: 70-75. They display small; artefacts are invisible.
If a platform imposes a hard byte limit (a job portal, an exam form), use the file size reducer, which searches the quality range for you rather than making you guess.
Step 5: Serve it properly
Optimised files can still be served badly. Four things are worth getting right.
Set width and height
Always put width and height attributes on <img>. The browser then reserves the correct space before the image arrives, preventing the page from jumping, which is what the Cumulative Layout Shift metric measures. The attributes carry the intrinsic pixel size; CSS still controls displayed size.
Lazy-load below the fold, never above it
loading="lazy" defers images until they approach the viewport. Do not put it on your hero image: that delays the very element LCP measures. Use loading="eager" and fetchpriority="high" there instead.
Offer responsive sources
A phone should not download the desktop hero. srcset lets the browser choose:
<img src="photo-1200.webp"
srcset="photo-600.webp 600w,
photo-1200.webp 1200w,
photo-2000.webp 2000w"
sizes="(max-width: 700px) 100vw, 700px"
width="1200" height="800"
alt="Descriptive text about the image">
Cache aggressively
Images rarely change. Serve them with a long Cache-Control lifetime and change the filename when the content changes, so returning visitors download nothing at all.
A worked example
A page with one hero photograph, six article images and a transparent PNG logo, before and after the workflow above:
| Asset | Before | After resize | After WebP q82 |
|---|---|---|---|
| Hero, 4032 × 3024 JPG | 3.8 MB | 620 KB (1800 px) | 190 KB |
| Six article photos | 7.2 MB | 1.1 MB (1200 px) | 340 KB |
| Logo, 1200 × 400 PNG | 310 KB | 78 KB (400 px) | 14 KB |
| Total | 11.3 MB | 1.8 MB | 544 KB |
That is roughly a 95% reduction, with the resize step alone accounting for most of it. These are representative figures from ordinary phone-camera content rather than a best case. Your own numbers will differ, and measuring them takes about two minutes.
Every tool referenced on this page runs in your browser. You can complete this entire workflow without uploading a single file anywhere.
Frequently asked questions
How small should images on a website be?
As a rule of thumb: under 200 KB for in-article images, under 300 KB for a full-width hero, under 50 KB for thumbnails, and under about 1 MB for all images on a page combined. These are targets rather than laws. A photography portfolio legitimately ships more.
Does image compression affect SEO?
Indirectly. Image files are not themselves a ranking factor, but they largely determine Largest Contentful Paint, which is a Core Web Vitals metric used in ranking. Faster pages also convert better, which is the more valuable outcome.
Should I use a plugin or do this manually?
For an existing site with hundreds of images, a plugin or build step is the practical answer. For new images going forward, doing it once at export time gives better results, because you can judge each image instead of applying one setting to everything.
What is a good Largest Contentful Paint score?
Google's threshold for a good score is 2.5 seconds or less, measured at the 75th percentile of real visits. If your LCP element is an image, resizing and converting it is usually the fastest route to getting under that.