Krunkit
Image Optimization
Web Performance
Tutorial

How to Reduce Website Image Size Without Losing Quality: A Step-by-Step Guide

A practical, beginner-friendly guide to reducing website image file sizes while maintaining visual quality. Covers format selection, quality settings, resizing, lazy loading, CDN delivery, and more.

Krunkit Team··14 min read

The Weight of Images on the Web

Images account for nearly half the total bytes transferred on the average webpage. According to HTTP Archive data from early 2026, the median webpage loads 2.1 MB of images — and the 90th percentile exceeds 5.8 MB. For context, the entire text content of most pages (HTML, CSS, JavaScript combined) is typically under 600 KB.

This matters because page weight directly impacts user experience. Every additional 100 KB adds roughly 30–50 ms of load time on a typical 4G connection, and much more on slower networks. Google's research consistently shows that users abandon pages that take more than 3 seconds to load, and image weight is the single largest controllable factor.

The good news: most websites can reduce image weight by 40–70% without any visible quality loss. The techniques are well understood, the tools are freely available, and the results are immediate. This guide walks through the process step by step.

Step 1: Audit Your Current Images

Before optimizing anything, you need to know what you are working with. A quick audit reveals where the biggest opportunities are.

Using Browser DevTools

Open Chrome DevTools (F12), go to the Network tab, and reload the page. Filter by Img to see only image requests.

Key columns to examine:

| Column | What to Look For | |--------|-----------------| | Size | Images over 200 KB are candidates for optimization | | Type | JPEG and PNG that could be WebP or AVIF | | Dimensions | Images loaded at 2000px but displayed at 400px | | Status | 200 (fresh download) vs 304 (cached) — check cache headers |

Using Lighthouse

Run a Lighthouse performance audit (in Chrome DevTools under the Lighthouse tab). Look for these specific opportunities:

  • "Serve images in next-gen formats" — images that should be WebP or AVIF
  • "Properly size images" — images downloaded at larger dimensions than displayed
  • "Efficiently encode images" — images that could be compressed further
  • "Defer offscreen images" — images below the fold that should be lazy loaded

Lighthouse estimates the potential savings in kilobytes for each opportunity. Start with the largest savings first.

Creating an Image Inventory

For larger sites, create a spreadsheet tracking:

  1. Image URL
  2. Current format
  3. File size
  4. Intrinsic dimensions (actual pixel width/height)
  5. Display dimensions (how large it appears on the page)
  6. Location (above or below the fold)
  7. Type (photo, illustration, icon, screenshot)

This inventory becomes your optimization plan. Prioritize images that are large, above the fold, and on high-traffic pages.

Step 2: Choose the Right Format for Each Image

Format selection is the single highest-impact optimization. Using the wrong format can cost you 2–5x in file size.

Decision Framework

Is it a photograph or complex image with many colors?
├── Yes → Use WebP (or AVIF for maximum compression)
│         Fallback: JPEG
└── No → Is it a simple graphic with flat colors, text, or sharp edges?
          ├── Yes → Does it need transparency?
          │         ├── Yes → Use WebP (or PNG if WebP is not an option)
          │         └── No → Use WebP (or optimized PNG for very simple graphics)
          └── Is it an icon or simple shape?
                    └── Use SVG (vector, infinitely scalable, tiny file size)

Format Comparison for a Typical Photo (2000x1500)

| Format | Quality Setting | File Size | Visual Quality | |--------|---------------|-----------|----------------| | Original PNG | N/A | 8.2 MB | Lossless | | JPEG | 85 | 420 KB | Excellent | | JPEG (MozJPEG) | 80 | 310 KB | Excellent | | WebP | 80 | 240 KB | Excellent | | AVIF | 60 | 165 KB | Excellent |

The difference between an unoptimized PNG and an AVIF is 50:1 — and the images look virtually identical to the human eye.

Browser Support in 2026

  • WebP: 97%+ global support. Safe to use as the primary format with JPEG fallback.
  • AVIF: 92%+ global support. Chrome, Firefox, Safari (16.4+), and Edge all support it. Fallback to WebP for older browsers.
  • JPEG XL: Still limited support. Chrome removed it, Firefox supports it behind a flag. Not recommended for production yet.

Use the <picture> element for format fallbacks:

<picture>
  <source srcset="photo.avif" type="image/avif" />
  <source srcset="photo.webp" type="image/webp" />
  <img src="photo.jpg" alt="Description" width="800" height="600" />
</picture>

Step 3: Set Optimal Quality Levels

Quality settings control the trade-off between file size and visual fidelity. The sweet spot varies by format and content type.

Recommended Quality Settings

| Format | Photos | UI/Screenshots | Graphics/Illustrations | |--------|--------|----------------|----------------------| | JPEG (MozJPEG) | 75–82 | 85–90 | 80–85 | | WebP | 75–82 | 82–88 | 78–85 | | AVIF | 55–68 | 65–75 | 60–70 |

AVIF's quality scale is different from JPEG and WebP — a quality of 60 in AVIF typically matches a quality of 80 in JPEG visually.

Finding Your Sweet Spot

The relationship between quality and file size is nonlinear. Reducing JPEG quality from 100 to 85 might cut file size by 60%, while going from 85 to 70 only saves another 25% — but the visual degradation becomes noticeable.

A practical approach:

  1. Start at quality 80 (JPEG/WebP) or 60 (AVIF)
  2. Compare with the original at 100% zoom
  3. If you cannot see a difference, try reducing by 5
  4. Stop when you notice artifacts — then go back one step

Tools like Krunkit make this process interactive: you can adjust the quality slider and immediately see the compressed result alongside the original, with file size updating in real time.

Content-Specific Adjustments

  • Hero images: Use higher quality (82–85 JPEG) — these are large, prominent, and first-impression content
  • Thumbnails: Lower quality is fine (70–75 JPEG) — small display size hides artifacts
  • Product photos: Higher quality (80–85 JPEG) — detail matters for purchase decisions
  • Blog post images: Medium quality (75–80 JPEG) — good enough for editorial content
  • Background images: Lower quality (70–75 JPEG), especially if a color overlay or blur is applied on top

Step 4: Resize to Actual Display Dimensions

This is the most commonly overlooked optimization, and often the most impactful.

The Problem

A smartphone camera produces images at 4000x3000 pixels (12 MP). If that image is displayed in a 400px-wide column on your website, the browser downloads 12 million pixels and then discards 97% of them to display 120,000 pixels.

The wasted bytes are enormous:

| Scenario | Image Dimensions | JPEG at q80 | Savings | |----------|-----------------|-------------|---------| | Original from camera | 4000 x 3000 | 1,200 KB | — | | Resized for display (2x) | 800 x 600 | 95 KB | 92% | | Resized for display (1x) | 400 x 300 | 32 KB | 97% |

How to Determine the Right Size

The image should be no larger than the largest size it will ever be displayed, multiplied by the device pixel ratio (DPR) you want to support.

For a responsive design where an image spans a column:

Optimal width = Max display width × Target DPR
  • 1x DPR (standard displays): rare now, most users have 2x+
  • 2x DPR (Retina, most smartphones and modern laptops): the practical target
  • 3x DPR (high-end phones): diminishing returns; 2x is usually sufficient

If your image displays at a maximum of 600px CSS width, generate it at 1200px (for 2x) and optionally 1800px (for 3x).

Responsive Images With srcset

The srcset attribute lets the browser choose the most appropriate image size:

<img
  src="photo-800.jpg"
  srcset="
    photo-400.jpg 400w,
    photo-800.jpg 800w,
    photo-1200.jpg 1200w
  "
  sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
  alt="Description"
  width="800"
  height="600"
/>

The sizes attribute tells the browser how wide the image will be displayed at different viewport widths, so it can calculate which srcset source to fetch before the layout is computed.

Batch Resizing

If you have dozens or hundreds of images to resize, doing it manually is impractical. Options:

  • Build-time: Use a Next.js image component, Gatsby image plugin, or a custom script with Sharp
  • CLI: sharp-cli, ImageMagick, or FFmpeg for batch operations
  • Browser-based: Tools like Krunkit can resize images in the browser without uploading

Step 5: Lazy Load Below-the-Fold Images

Images that are not visible when the page first loads should not block the initial page render. Lazy loading defers their download until the user scrolls near them.

Native Lazy Loading

The simplest approach — supported in all modern browsers:

<img src="photo.jpg" alt="Description" loading="lazy" width="800" height="600" />

The browser handles the intersection detection and loading timing automatically. The width and height attributes are critical — they allow the browser to reserve the correct space before the image loads, preventing layout shift.

What to Lazy Load (and What Not To)

Lazy load:

  • Images below the first viewport (below the fold)
  • Images in tabs, accordions, or carousels that are not initially visible
  • Thumbnails in long gallery pages

Do NOT lazy load:

  • The hero image or any image visible on initial page load
  • The Largest Contentful Paint (LCP) element (this is almost always above the fold)
  • Logo and navigation images

For the LCP image, do the opposite of lazy loading — preload it:

<link rel="preload" as="image" href="hero-image.webp" type="image/webp" />

Placeholder Strategies

While a lazy-loaded image is pending, the space appears empty (or collapses if width/height are missing). Better approaches:

  • Solid color placeholder: Use the image's dominant color as the background of the container. Minimal overhead.
  • Blurred low-quality preview (LQIP): Inline a tiny (20x15 pixel) base64-encoded version as a blurred background. Adds ~300 bytes per image.
  • CSS aspect-ratio: Modern browsers support aspect-ratio: 4/3 to reserve space without any placeholder image.
.image-container {
  aspect-ratio: 4 / 3;
  background-color: #e2e8f0;
}

Step 6: Use a CDN for Image Delivery

A Content Delivery Network caches your images on servers distributed globally, so users download from a nearby location instead of your origin server.

Why CDN Matters for Images

| Without CDN | With CDN | |------------|---------| | User in Tokyo requests image from US server: ~200 ms latency | User in Tokyo requests from Tokyo edge node: ~15 ms latency | | Origin server handles all traffic | Traffic distributed across edge nodes | | No automatic format negotiation | Many CDNs auto-convert to WebP/AVIF based on browser support |

Image CDN Services

Dedicated image CDNs go beyond simple caching — they transform images on the fly:

  • Cloudflare Images / Polish: Automatic WebP/AVIF conversion, resizing via URL parameters
  • Imgix: URL-based transformations (resize, crop, format, quality)
  • Cloudinary: Full image management with transformations, optimization, and AI features
  • Vercel Image Optimization: Built into Next.js, automatic format negotiation and resizing

URL-based transformation example (Imgix):

https://your-site.imgix.net/photo.jpg?w=800&auto=format&q=75

This delivers an 800px-wide image in the optimal format for the requesting browser at quality 75 — all from a single source image.

Self-Hosted Alternative

If you prefer not to use a third-party service, you can still benefit from CDN caching:

  1. Optimize images at build time (using Sharp, Squoosh CLI, or similar)
  2. Generate multiple sizes and formats
  3. Serve through a general-purpose CDN (Cloudflare, Fastly, AWS CloudFront)
  4. Set appropriate cache headers: Cache-Control: public, max-age=31536000, immutable for fingerprinted image URLs

Step 7: Implement Proper Cache Headers

Caching is the final piece. A well-cached image is never re-downloaded.

Cache Strategy for Images

# Images with content hash in filename (e.g., photo-a3f8b2.webp)
Cache-Control: public, max-age=31536000, immutable

# Images without hash (e.g., logo.png)
Cache-Control: public, max-age=86400
ETag: "abc123"
  • Immutable + long max-age: For fingerprinted images. The browser will never revalidate. When the image changes, the filename changes.
  • Moderate max-age + ETag: For images that might change (logo, favicon). The browser revalidates after 24 hours, and the ETag check avoids re-downloading if unchanged.

Common Caching Mistakes

  1. No cache headers at all: Every page load re-downloads every image. Surprisingly common.
  2. no-cache on images: Forces revalidation on every request. Only appropriate for highly dynamic images.
  3. Short max-age without ETag: Forces full re-download every expiry period.

Putting It All Together: A Real-World Example

Let's walk through optimizing a typical blog page with 8 images.

Before Optimization

| Image | Format | Dimensions | File Size | |-------|--------|-----------|-----------| | Hero photo | PNG | 3840 x 2160 | 6.8 MB | | Author avatar | PNG | 1000 x 1000 | 420 KB | | 4x inline photos | JPEG (q95) | 2400 x 1600 | 1.1 MB each | | Diagram | PNG | 1800 x 1200 | 890 KB | | CTA background | JPEG (q100) | 1920 x 800 | 780 KB | | Total | | | 13.3 MB |

After Optimization

| Image | Changes Applied | New Size | Savings | |-------|----------------|----------|---------| | Hero photo | WebP, resized to 1600w, q80 | 82 KB | 99% | | Author avatar | WebP, resized to 200w, q80 | 8 KB | 98% | | 4x inline photos | WebP, resized to 1200w, q78 | 68 KB each | 94% | | Diagram | Optimized PNG (OxiPNG) | 210 KB | 76% | | CTA background | WebP, resized to 1200w, q72 | 45 KB | 94% | | Total | | 617 KB | 95% |

From 13.3 MB to 617 KB — a 95% reduction with no perceptible quality loss. Page load time on a 4G connection drops from ~8 seconds to under 1.5 seconds.

The Optimization Checklist

For each image on your site, work through this list:

  • [ ] Is it the right format? (Photo → WebP/AVIF, graphic → SVG/WebP, icon → SVG)
  • [ ] Is it compressed with an optimal quality setting? (Not q100 or q95)
  • [ ] Is it sized to actual display dimensions × 2 (for Retina)?
  • [ ] Is it lazy loaded (if below the fold)?
  • [ ] Is the LCP image preloaded (if above the fold)?
  • [ ] Does it have width and height attributes (prevent layout shift)?
  • [ ] Does it have appropriate alt text (accessibility)?
  • [ ] Is it served from a CDN with proper cache headers?

Quick Wins for Right Now

If you are looking for immediate impact without a full optimization overhaul:

  1. Convert your 3 largest images to WebP at quality 80. This alone can save megabytes.
  2. Add loading="lazy" to all images below the fold. One attribute, instant improvement.
  3. Add width and height to every <img> tag. Eliminates layout shift — a Core Web Vital.
  4. Preload your LCP image. One <link> tag that can shave hundreds of milliseconds off your LCP score.

These four changes take less than an hour and can improve your Lighthouse performance score by 10–20 points.

Tools for the Job

Browser-Based (No Upload Required)

  • Krunkit — Compress, convert, and resize images entirely in your browser using WebAssembly. No upload, no server, no privacy concerns. Supports JPEG, PNG, WebP, and AVIF.
  • Squoosh (by Google) — Single-image optimization with codec comparison

CLI / Build Tools

  • Sharp — High-performance Node.js image processing (libvips-based)
  • Squoosh CLI — Command-line version of Squoosh
  • ImageMagick — The classic Swiss army knife of image processing

Analysis

  • Lighthouse — Built into Chrome DevTools
  • WebPageTest — Detailed waterfall analysis
  • PageSpeed Insights — Google's online performance analysis

Conclusion

Reducing website image size is not a single technique — it is a combination of choosing the right format, setting appropriate quality, resizing to actual display dimensions, lazy loading, and delivering through a CDN with proper caching. Each step contributes, and together they can reduce image weight by 80–95%.

The effort-to-impact ratio is exceptional. Most of these optimizations are one-time setup tasks. Once your workflow includes format conversion, resizing, and lazy loading, every new image you add benefits automatically.

Start with the audit. Find your largest images. Apply the checklist. The results will show up in your performance metrics, your users' experience, and your hosting bill.