Skip to content
intermediatePhase 38 · Web Performance

Image Optimization

Optimize images with modern formats, responsive sizing, and CDN delivery.

45m
0 problems
Topic Progress0%

Modern Formats

Modern Formats

Use next-gen image formats for better compression.

WebP vs JPEG vs PNG

Format Compression Transparency Animation Browser Support
JPEG Lossy No No 100%
PNG Lossless Yes No 100%
WebP Both Yes Yes 97%+
AVIF Both Yes Yes 92%+

Implementing WebP

// Serve WebP with fallback
function OptimizedImage({ src, alt, width, height }) {
  return (
    <picture>
      <source srcSet={`${src}.webp`} type="image/webp" />
      <source srcSet={`${src}.jpg`} type="image/jpeg" />
      <img
        src={`${src}.jpg`}
        alt={alt}
        width={width}
        height={height}
        loading="lazy"
      />
    </picture>
  );
}

// Usage
<OptimizedImage
  src="/images/hero"
  alt="Hero image"
  width={1200}
  height={600}
/>

AVIF Support

function NextGenImage({ src, alt, width, height }) {
  return (
    <picture>
      <source srcSet={`${src}.avif`} type="image/avif" />
      <source srcSet={`${src}.webp`} type="image/webp" />
      <img
        src={`${src}.jpg`}
        alt={alt}
        width={width}
        height={height}
        loading="lazy"
        decoding="async"
      />
    </picture>
  );
}

Image Processing with Sharp

// Server-side image processing
const sharp = require('sharp');

async function processImage(inputPath, outputPath) {
  await sharp(inputPath)
    .resize(1200, 630, { fit: 'cover' })
    .webp({ quality: 80 })
    .toFile(`${outputPath}.webp`);

  await sharp(inputPath)
    .resize(1200, 630, { fit: 'cover' })
    .jpeg({ quality: 80, progressive: true })
    .toFile(`${outputPath}.jpg`);
}

Quality Settings

// Recommended quality settings
const qualitySettings = {
  webp: { quality: 80, effort: 4 },
  jpeg: { quality: 80, progressive: true },
  avif: { quality: 65, effort: 4 },
  png: { compressionLevel: 6 },
};

Responsive Images

Responsive Images

Serve appropriately sized images for different devices.

srcset and sizes

function ResponsiveImage({ src, alt }) {
  return (
    <img
      src={`${src}-800.jpg`}
      srcset={
        `${src}-400.jpg 400w,
         ${src}-800.jpg 800w,
         ${src}-1200.jpg 1200w,
         ${src}-1600.jpg 1600w`
      }
      sizes={
        "(max-width: 640px) 100vw,
         (max-width: 1024px) 50vw,
         33vw"
      }
      alt={alt}
      loading="lazy"
      width={800}
      height={600}
    />
  );
}

Art Direction

function HeroImage() {
  return (
    <picture>
      {/* Mobile: cropped close-up */}
      <source
        media="(max-width: 768px)"
        srcSet="/hero-mobile.webp"
        type="image/webp"
      />
      <source
        media="(max-width: 768px)"
        srcSet="/hero-mobile.jpg"
      />
      {/* Desktop: full image */}
      <source
        srcSet="/hero-desktop.webp"
        type="image/webp"
      />
      <img
        src="/hero-desktop.jpg"
        alt="Hero"
        className="hero-image"
      />
    </picture>
  );
}

Image CDN

// Using an image CDN like Cloudinary or imgix
function CDNOptimizedImage({ publicId, alt, width, height }) {
  const baseUrl = 'https://res.cloudinary.com/demo/image/upload';
  
  return (
    <img
      src={`${baseUrl}/w_${width},h_${height},f_auto,q_auto/${publicId}`}
      srcset={
        `${baseUrl}/w_400,h_300,f_auto,q_auto/${publicId} 400w,
         ${baseUrl}/w_800,h_600,f_auto,q_auto/${publicId} 800w,
         ${baseUrl}/w_1200,h_900,f_auto,q_auto/${publicId} 1200w`
      }
      sizes="(max-width: 768px) 100vw, 50vw"
      alt={alt}
      width={width}
      height={height}
      loading="lazy"
    />
  );
}

CSS Image Optimization

/* Object-fit for consistent sizing */
.image-container {
  width: 100%;
  height: 300px;
  overflow: hidden;
}

.image-container img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Content visibility for below-fold images */
.below-fold-images {
  content-visibility: auto;
  contain-intrinsic-size: 0 500px;
}

Image CDN

Image CDN

Use a CDN for automatic image optimization.

Cloudinary

function CloudinaryImage({ publicId, width, height }) {
  const url = `https://res.cloudinary.com/demo/image/upload`;
  
  return (
    <img
      src={`${url}/w_${width},h_${height},f_auto,q_auto/${publicId}`}
      srcset={
        `${url}/w_400,f_auto/${publicId} 400w,
         ${url}/w_800,f_auto/${publicId} 800w,
         ${url}/w_1200,f_auto/${publicId} 1200w`
      }
      sizes="(max-width: 768px) 100vw, 50vw"
      alt=""
      loading="lazy"
    />
  );
}

// Transformations
const transformations = {
  thumbnail: 'w_150,h_150,c_fill,g_face',
  card: 'w_400,h_300,c_fill',
  hero: 'w_1920,h_1080,c_fill',
  avatar: 'w_100,h_100,c_fill,g_face,r_max',
};

imgix

function ImgixImage({ src, alt, width, height }) {
  const params = new URLSearchParams({
    w: width,
    h: height,
    fit: 'crop',
    auto: 'format,compress',
  });

  return (
    <img
      src={`${src}?${params}`}
      srcset={
        `${src}?w=400&auto=format 400w,
         ${src}?w=800&auto=format 800w,
         ${src}?w=1200&auto=format 1200w`
      }
      sizes="(max-width: 768px) 100vw, 50vw"
      alt={alt}
      loading="lazy"
    />
  );
}

Self-Hosted with Next.js

// next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048],
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    minimumCacheTTL: 60 * 60 * 24 * 30, // 30 days
  },
};

// Component
import Image from 'next/image';

function OptimizedImage({ src, alt }) {
  return (
    <Image
      src={src}
      alt={alt}
      width={800}
      height={600}
      placeholder="blur"
      blurDataURL="data:image/jpeg;base64,/9j/4AAQ..."
    />
  );
}

Best Practices

  1. Use modern formats: WebP/AVIF with fallbacks
  2. Implement srcset: Serve appropriate sizes
  3. Lazy load: Use loading="lazy" for below-fold
  4. Set dimensions: Prevent CLS
  5. Use CDN: Automatic optimization and caching
  6. Compress: Reduce file sizes
  7. Cache: Set proper cache headers

Practice Problems

0/3solved
Build Image Optimization Component

Create a reusable React component implementing Image Optimization. Include proper state management and accessibility.

Solution
// Production-ready component with:
// - Proper TypeScript types
// - Accessibility (ARIA)
// - Error boundaries
// - Loading states
// - Memoization where needed
Image Optimization Testing

Write unit and integration tests for Image Optimization using React Testing Library.

Solution
// Test coverage:
// 1. Rendering tests
// 2. Interaction tests
// 3. Edge case tests
// 4. Accessibility tests
Image Optimization Performance

Optimize Image Optimization for performance. Consider memoization, code splitting, and bundle size.

Solution
// Optimization techniques:
// 1. React.memo / useMemo / useCallback
// 2. Code splitting with lazy()
// 3. Virtual scrolling for lists
// 4. Image lazy loading
// 5. Bundle analysis

Quiz

1. What is the main benefit of WebP over JPEG?

Question 1 options

2. What does srcset allow?

Question 2 options

3. Why use an image CDN?

Question 3 options

4. What is art direction in responsive images?

Question 4 options

5. Why set image dimensions?

Question 5 options

Flashcards

Question

What is WebP?

Answer

A modern image format that provides better compression than JPEG/PNG with support for transparency and animation.

Question

What does srcset do?

Answer

Allows the browser to choose the most appropriate image based on viewport size and device pixel ratio.

Question

What is art direction?

Answer

Serving different image crops optimized for different viewport sizes using the <picture> element.

Question

Why use an image CDN?

Answer

Automatic optimization, resizing, format conversion, and global caching for faster delivery.

Question

What is Image Optimization?

Answer

Image Optimization is a key concept in frontend development.

Revision Notes

Key Takeaways

  • 1.WebP and AVIF provide better compression than JPEG/PNG
  • 2.srcset enables responsive images for different viewports
  • 3.Image CDNs handle optimization automatically
  • 4.Art direction serves different crops for different viewports
  • 5.Always set dimensions to prevent CLS

Interview Tips

  • Explain the benefits of WebP over JPEG
  • Discuss how srcset and sizes work together
  • Know when to use art direction vs responsive sizing

Cheat Sheet

Image Optimization Cheat Sheet

Modern Formats

  • WebP: 25-34% smaller than JPEG
  • AVIF: Even better compression
  • Use for fallbacks

Responsive Images

<img
  srcSet="img-400.jpg 400w, img-800.jpg 800w"
  sizes="(max-width: 768px) 100vw, 50vw"
/>

Best Practices

  1. Use WebP/AVIF with fallbacks
  2. Implement srcset for responsive
  3. Lazy load below-fold images
  4. Set width/height for CLS
  5. Use CDN for optimization
  6. Compress to 80% quality