How to Optimize Images for the Web (Without Losing Quality)
A step-by-step guide to making images load faster on your website without sacrificing visual quality. Covers resize, compress, format, lazy loading, and srcset.
Images are usually the biggest weight on any web page. A typical e-commerce product page or blog post downloads more bytes of image data than HTML, CSS, JavaScript, and fonts combined. Most of those bytes are wasted — sites serve full-resolution camera output to displays that are showing the image at a tenth of the original size, and they do it at quality settings far higher than the eye can perceive.
Fixing this isn't complicated, but the order matters. Done in the right sequence, you can reliably cut image weight by 80% or more on most sites without any visible loss of quality. Done in the wrong sequence, you waste effort and can even make things worse. This guide walks through the optimal order of operations.
Step 1: Resize to the actual display size
The single highest-leverage optimization is resizing images down to the dimensions they actually display at. A photo coming out of a modern phone is 4032×3024 pixels (12 megapixels) or larger. A typical hero image on a website displays at maybe 1600 pixels wide. Everything beyond that width is invisible to the user but has to be downloaded.
For most websites, 2000 pixels on the longest side is the maximum useful resolution. High-DPI displays (Retina, modern phones, 4K monitors) want 2× the displayed CSS pixels, so a 1000-pixel-wide layout slot wants a 2000-pixel image to look crisp on high-DPI screens. Anything beyond that is wasted bytes.
Resize before compressing. Compressing a 4000-pixel image and then resizing it later wastes the quality budget on pixels that will never be seen. Compressing after resizing lets the encoder focus on the pixels you actually display.
Practical targets: hero images 1600–2400 pixels wide, content images 800–1200 wide, thumbnails 300–600 wide. Adjust to your layout. The resizer makes this a one-step batch operation.
Step 2: Pick the right format
After resizing, decide which format the destination wants. For most modern websites, the answer is WebP — it's 25–35% smaller than JPG at equivalent quality and supported by every current browser. For older systems that still require JPG, picking JPG is the safe fallback.
Screenshots, logos, and graphics with sharp edges or transparency should stay as PNG, or convert to lossless WebP for additional savings. Photographic content should always be JPG or lossy WebP — saving photos as PNG bloats the file 3–5× with no quality advantage.
If you control the platform (your own website, app, or product), default to WebP. If you're handing the image off to a system you don't control (a third-party CMS, an email recipient, a government form), check what they accept and pick accordingly.
Step 3: Compress to the right quality
Quality 80 is the sweet spot for photographic JPG and WebP. Below 70, you start to see compression artifacts: block boundaries in flat regions, color banding in skies, ringing around hard edges. Above 90, you're spending bytes that nobody can perceive.
For screenshots and graphics with sharp edges, lossless WebP or PNG are usually the right call. Lossy compression of UI screenshots looks visibly worse — quality 90+ may be acceptable but lossless is safer.
Compare side-by-side before committing. The compression tool's hover-to-compare feature is genuinely useful here: hover over the result and the original appears underneath at full quality. If you can spot a difference, bump the quality up. If you can't, lower it further to save more bytes.
Typical real-world savings: a 6 MB phone photo compresses to 600–800 KB as JPG quality 80 with no visible change. The same photo as WebP quality 80 is typically 400–500 KB. That's a 10–15× reduction in file size from a single five-second operation.
Step 4: Strip EXIF metadata
Phone photos carry 30–100 KB of EXIF metadata: camera model, lens info, shooting settings, and most importantly GPS coordinates of where the photo was taken. For web use this is pure overhead — the browser doesn't need any of it to display the image, and the GPS data is often something you actively don't want to publish.
Stripping EXIF removes the metadata without re-encoding pixels, so visual quality is identical and the file shrinks by the metadata size. For batch workflows, running images through the resizer or format converter strips EXIF as a side effect of the re-encode. For single images where you want to inspect what's there first, our EXIF Viewer & Remover surfaces every tag before you strip.
Important privacy note: GPS coordinates in EXIF can reveal home addresses, school locations, workplaces, and travel patterns to anyone who downloads a photo. Major social platforms strip EXIF on upload, but many smaller channels (email, file uploads, forums, marketplaces, messaging apps) preserve it. If you're publishing a photo outside the big social platforms, strip EXIF first.
Step 5: Serve responsive images with srcset
Even an optimally compressed 1600-pixel image is too big for a phone displaying it at 320 pixels wide. The fix is the HTML srcset attribute, which lets you offer multiple versions of the same image and let the browser pick the right one based on the device's screen size and resolution.
A typical srcset for a content image: provide a 600-pixel, 1200-pixel, and 2000-pixel version. The browser downloads the smallest version that's big enough for the displayed size at the user's pixel density. Phones download the 600-pixel version; high-DPI laptops download the 1200; 4K monitors download the 2000.
Producing the three versions is a one-step batch in the resizer: set 600, then 1200, then 2000 as percentage or pixel targets and process each batch. Then reference all three in your HTML.
Example: <img srcset="hero-600.webp 600w, hero-1200.webp 1200w, hero-2000.webp 2000w" sizes="(max-width: 768px) 100vw, 50vw" src="hero-1200.webp" alt="...">. The browser does the rest.
Step 6: Add lazy loading
Images below the fold don't need to load until the user scrolls toward them. The HTML loading="lazy" attribute tells the browser to defer those downloads automatically. It costs nothing to add and significantly improves perceived page load on long pages.
Use loading="lazy" on all images that aren't visible in the initial viewport. Use loading="eager" (the default) only on hero images and anything else above the fold. For LCP (Largest Contentful Paint) optimization, the main hero image should also have fetchpriority="high" so the browser fetches it ahead of other resources.
Most static site generators and modern CMSes do this automatically. If you're hand-writing HTML or working with an older system, adding loading="lazy" is a one-attribute change that typically saves 30–60% of initial page weight.
Step 7: Prevent layout shift with explicit dimensions
An image without explicit width and height attributes causes the page to reflow when it finishes loading — the content below jumps down to make room. This is bad for user experience and hurts Cumulative Layout Shift (CLS), a key Core Web Vitals metric.
Always set width and height attributes on <img> tags (and on the equivalent props in framework Image components). The browser uses these to reserve the right amount of space before the image arrives, eliminating layout shift.
The values don't have to match the actual displayed size; they're used as an aspect ratio. A 1200×800 image declared with width="1200" and height="800" reserves a 3:2 aspect ratio box scaled to whatever the CSS layout assigns.
Putting it all together: a real example
Take a 6 MB iPhone photo destined for a blog post. After our pipeline: resize to 1600 pixels wide (the layout's max), convert to WebP, compress at quality 80, strip EXIF. Output: roughly 250–350 KB instead of 6 MB. That's a 95% reduction with no visible loss.
Generate two more sizes (800 and 1200) for srcset. Total bandwidth for serving the image responsively: roughly 700 KB across all three versions, of which any single visitor downloads only one. Compare to the original 6 MB everyone-downloads-the-same-thing approach: a 90%+ reduction in real-world bandwidth.
On a content-heavy page with 20 images, this is the difference between a 100 MB initial download (catastrophic on mobile) and a 5–10 MB initial download (comfortable everywhere). Multiply by every visitor over the lifetime of the page and the savings are massive — both for your hosting costs and for everyone using your site.
Wrapping up
Image optimization is one of those rare cases where you can deliver a dramatically better user experience with no creative trade-off — the user sees the same images, just faster. The five-step pipeline (resize, format, compress, strip EXIF, serve responsively) takes about fifteen minutes to set up for a typical site and pays back forever.
Our tools cover the first four steps client-side and free. The last two (srcset and lazy loading) are HTML attributes anyone can add by hand or wire into a static site build. Start with resize and compress — those two alone usually cut image weight by 80%+ on the average site.
Tools mentioned in this guide
More guides
- PNG vs JPG vs WebP: Which Image Format Should You Use in 2026?
Pick PNG for screenshots and transparency. Pick JPG for photos that need universal compatibility. Pick WebP for everything else — it's smaller, sharper, and works in every modern browser.
- EXIF Metadata Explained: What Your Photos Reveal About You
Every photo your phone takes records exactly when, where, and how it was captured. That data travels with the file unless you strip it. Here's what's in there, who can read it, and how to remove it before sharing.
- Favicon Best Practices: A Complete Guide for 2026
A good favicon takes ten minutes to set up and benefits every visitor forever. Here's the complete 2026 checklist — what sizes you need, where to put them, and how to make them look sharp on every device.