Back to blog
PerformanceJanuary 1, 2024· 6 min read

Image Optimization Detection: Is This Site Wasting Bandwidth?

A practical Fusebox guide to image optimization detection.

Image Optimization Detection: Is This Site Wasting Bandwidth?

Published: January 2024
Reading time: 8 minutes

Images are usually the heaviest part of any website. A single unoptimized image can be larger than your entire JavaScript bundle. Here's how to detect optimization issues and why they matter.

The Image Weight Problem

E-commerce Homepage:

Total page size: 8.2MB
Images: 6.8MB (83%)
- Hero banner: 2.1MB (PNG!)
- Product images: 4.2MB (unoptimized JPEGs)
- Icons: 0.5MB (should be SVG)

News Article:

Total page size: 4.5MB
Images: 3.9MB (87%)
- Featured image: 1.8MB (4000x3000px displayed at 800x600)
- Inline images: 2.1MB (no lazy loading)

These sites are forcing users to download 5-10x more data than necessary.

How to Detect Image Issues

1. Quick Console Audit

// Paste this to analyze current page
(function imageAudit() {
  const images = Array.from(document.images);
  let totalSize = 0;
  let issues = [];
  
  images.forEach(img => {
    // Get natural vs display size
    const natural = img.naturalWidth * img.naturalHeight;
    const display = img.clientWidth * img.clientHeight;
    const ratio = natural / display;
    
    if (ratio > 2) {
      issues.push({
        src: img.src,
        natural: `${img.naturalWidth}x${img.naturalHeight}`,
        display: `${img.clientWidth}x${img.clientHeight}`,
        waste: `${((ratio - 1) * 100).toFixed(0)}% too large`
      });
    }
  });
  
  console.table(issues);
  
  // Check formats
  const formats = {};
  images.forEach(img => {
    const ext = img.src.split('.').pop().split('?')[0].toLowerCase();
    formats[ext] = (formats[ext] || 0) + 1;
  });
  
  console.log('Image formats:', formats);
  
  // Performance entries
  const imageResources = performance.getEntriesByType('resource')
    .filter(r => r.name.match(/\.(jpg|jpeg|png|gif|webp|avif)$/i));
  
  imageResources.forEach(resource => {
    totalSize += resource.transferSize || 0;
  });
  
  console.log(`Total image size: ${(totalSize / 1024 / 1024).toFixed(1)}MB`);
})();

2. Dimension Analysis

// Oversized images waste bandwidth
const oversizedImages = Array.from(document.images).filter(img => {
  const displayed = img.clientWidth * img.clientHeight;
  const actual = img.naturalWidth * img.naturalHeight;
  return actual > displayed * 1.5; // 50% larger than needed
});

console.log(`Found ${oversizedImages.length} oversized images`);

3. Format Detection

// Check for modern formats
const images = performance.getEntriesByType('resource')
  .filter(r => r.name.match(/\.(jpg|jpeg|png|gif|webp|avif)$/i));

const formats = {
  legacy: 0,  // JPG, PNG, GIF
  modern: 0   // WebP, AVIF
};

images.forEach(img => {
  if (img.name.match(/\.(webp|avif)$/i)) {
    formats.modern++;
  } else {
    formats.legacy++;
  }
});

console.log(`Modern formats: ${formats.modern}/${images.length}`);

Common Image Problems

1. Wrong Format for Content

PNG for Photos (Bad)

<img src="team-photo.png" alt="Our team">
<!-- 2.8MB PNG → should be 280KB JPEG -->

JPEG for Graphics (Bad)

<img src="logo.jpg" alt="Company logo">
<!-- Blurry edges, artifacts → should be SVG -->

Right Format Guide:

  • Photos: JPEG, WebP, AVIF
  • Graphics/Logos: SVG (scalable) or PNG
  • Animations: Video (MP4) not GIF
  • Icons: SVG or icon fonts

2. Serving Desktop Images to Mobile

The Problem:

<!-- Same image for all devices -->
<img src="hero-4000x2000.jpg" alt="Hero">

<!-- Mobile (375px): Downloads 4000px image -->
<!-- Tablet (768px): Downloads 4000px image -->
<!-- Desktop (1920px): Uses 4000px image -->

The Solution:

<picture>
  <source media="(max-width: 640px)" 
          srcset="hero-640.webp" 
          type="image/webp">
  <source media="(max-width: 1024px)" 
          srcset="hero-1024.webp" 
          type="image/webp">
  <source srcset="hero-2048.webp" 
          type="image/webp">
  <img src="hero-2048.jpg" alt="Hero">
</picture>

3. No Lazy Loading

Loading everything immediately:

<!-- Page has 50 images, all load immediately -->
<img src="image1.jpg">
<img src="image2.jpg">
<!-- ... 48 more -->

Smart lazy loading:

<!-- Above fold: Load immediately -->
<img src="hero.jpg" loading="eager">

<!-- Below fold: Load when needed -->
<img src="image2.jpg" loading="lazy">
<img src="image3.jpg" loading="lazy">

4. Missing Compression

Unoptimized vs Optimized:

Original photo.jpg: 3.2MB
After optimization: 320KB (90% smaller!)
Same visual quality to users

Real-World Examples

Example 1: Blog with Heavy Images

Found Issues:

{
  "total_images": 23,
  "total_size": "18.4MB",
  "problems": {
    "oversized": 19,
    "wrong_format": 8,
    "no_lazy_loading": 23,
    "no_srcset": 23
  }
}

Specific Problems:

author-photo.png: 890KB → Should be 45KB JPEG
screenshot1.png: 2.1MB → Should be 180KB JPEG  
icon-set.png: 340KB → Should be 8KB SVG sprite

Impact: Page loads in 12 seconds on 4G

Analysis:

// Main product image
{
  file: "product-main.jpg",
  dimensions: "4000x4000",
  displayed: "600x600",
  size: "3.8MB",
  waste: "98.5% pixels not shown"
}

// Thumbnails
{
  files: 8,
  total_size: "4.2MB",
  displayed_size: "100x100 each",
  optimal_size: "~200KB total"
}

Fix Applied:

<!-- Responsive images -->
<img srcset="product-600.webp 600w,
             product-1200.webp 1200w,
             product-2400.webp 2400w"
     sizes="(max-width: 600px) 100vw, 600px"
     src="product-600.jpg"
     loading="lazy">

Result: 3.8MB → 380KB (90% reduction)

Example 3: Restaurant Website

Hero Section Disaster:

hero-background.jpg:
- File size: 5.2MB
- Dimensions: 5472x3648
- Display area: 1920x600
- Visible portion: 10%
- Loading time: 8 seconds

Multiple Issues:

  1. Using photo dimensions for web
  2. No compression
  3. Loading full image for banner crop
  4. JPEG instead of WebP

Image Optimization Techniques

1. Modern Formats

WebP (25-35% smaller than JPEG):

<picture>
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="Fallback for old browsers">
</picture>

AVIF (50% smaller than JPEG):

<picture>
  <source srcset="image.avif" type="image/avif">
  <source srcset="image.webp" type="image/webp">
  <img src="image.jpg" alt="Progressive enhancement">
</picture>

2. Responsive Images

srcset for Resolution:

<img srcset="small.jpg 1x, large.jpg 2x"
     src="small.jpg"
     alt="Retina support">

sizes for Viewport:

<img srcset="image-400.jpg 400w,
             image-800.jpg 800w,
             image-1200.jpg 1200w"
     sizes="(max-width: 400px) 100vw,
            (max-width: 800px) 50vw,
            400px"
     src="image-400.jpg">

3. Compression Levels

// Typical savings
const compression = {
  'PNG': {
    lossless: '10-30% smaller',
    lossy: '60-80% smaller'
  },
  'JPEG': {
    quality85: '40-60% smaller',
    quality75: '60-80% smaller'
  },
  'WebP': {
    lossless: '26% smaller than PNG',
    lossy: '25-34% smaller than JPEG'
  }
};

4. Lazy Loading Strategies

// Native lazy loading
<img loading="lazy" src="image.jpg">

// Intersection Observer (more control)
const images = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries) => {
  entries.forEach(entry => {
    if (entry.isIntersecting) {
      const img = entry.target;
      img.src = img.dataset.src;
      imageObserver.unobserve(img);
    }
  });
});

images.forEach(img => imageObserver.observe(img));

Quick Optimization Checklist

Format Selection

  • Photos in WebP/JPEG, not PNG
  • Graphics/logos in SVG
  • No BMP or TIFF on web
  • GIFs → MP4 videos

Size Optimization

  • Images sized for display
  • Responsive images implemented
  • Retina handled efficiently
  • Compression applied

Loading Strategy

  • Lazy loading enabled
  • Critical images prioritized
  • Progressive JPEG for large images
  • Placeholder/blur while loading

Performance

  • Total image weight < 1MB per page
  • No single image > 500KB
  • CDN serving images
  • Browser caching configured

Detection Tools

Browser DevTools

1. Network tab → Filter: Img
2. Sort by size (largest first)
3. Check "Disable cache"
4. Look for:
   - Red flags: > 500KB images
   - Format: Avoid PNG for photos
   - Dimensions vs display size

Lighthouse Report

Images section shows:
- Properly size images
- Serve images in next-gen formats
- Efficiently encode images
- Use lazy loading

Performance API

// Get image performance data
const images = performance.getEntriesByType('resource')
  .filter(entry => entry.name.match(/\.(jpg|jpeg|png|gif|webp|avif)/i))
  .sort((a, b) => b.transferSize - a.transferSize);

console.table(images.map(img => ({
  url: img.name.split('/').pop(),
  size: `${(img.transferSize / 1024).toFixed(0)}KB`,
  time: `${img.duration.toFixed(0)}ms`
})));

The Business Impact

Real Numbers

  • Amazon: 1 second delay = $1.6B lost sales/year
  • Google: 0.5 second delay = 20% traffic drop
  • Pinterest: 40% faster = 15% more signups

Your Impact

Before optimization:
- Image weight: 12MB
- Load time: 8.5s
- Bounce rate: 68%

After optimization:
- Image weight: 1.8MB (85% reduction)
- Load time: 2.1s
- Bounce rate: 32%

Result: 2x conversions

The Bottom Line

Image optimization is the easiest performance win:

  • Huge impact (often 50-90% size reduction)
  • Simple fixes (compression, formats, lazy load)
  • Immediate results (faster loads, happier users)
  • Better SEO (Core Web Vitals improvement)

Every unoptimized image is bandwidth stolen from your users.


Detect image optimization issues instantly: Fusebox analyzes all images for size, format, and loading issues while you browse. See optimization opportunities immediately. $29 one-time purchase.