# Responsive Images

**MUST** · **ID:** `performance-responsive-images` · **Category:** performance
**Source:** [Web Platform](https://web.dev/)
**Interactive version:** https://ui-guides-agent-rules.netlify.app/principles/performance-responsive-images

> MUST: Use `srcset` + `sizes` for responsive images. Serve WebP/AVIF with `<picture>` fallback. Always set explicit `width`/`height` attributes or CSS `aspect-ratio` to prevent CLS.

Serve optimally-sized images for each device with srcset, sizes, and modern formats

Without responsive images, mobile users download desktop-sized images, wasting bandwidth and slowing LCP. srcset lets browsers choose optimal sizes. Modern formats (WebP, AVIF) reduce file size 25-50%.

## Bad — do not do this

`performance-responsive-images-bad`

```tsx
export function ResponsiveImagesBad() {
  return (
    <div className="w-full max-w-md">
      <div className="bg-card border border-border rounded-lg overflow-hidden">
        {/* Single large image for all devices */}
        <img
          src="https://images.pexels.com/photos/1181671/pexels-photo-1181671.jpeg?auto=compress&cs=tinysrgb&w=1600"
          alt="Developer working at a desk with multiple monitors showing code"
          className="w-full h-48 object-cover"
        />
        <div className="p-4">
          <h3 className="font-semibold mb-2">Product Showcase</h3>
          <p className="text-sm text-muted-foreground">
            This 1600px image loads on all devices, even 375px phones.
          </p>
        </div>
      </div>
      <div className="mt-4 p-3 bg-error/10 border border-error/30 rounded text-sm">
        <p className="font-medium text-error">Problems:</p>
        <ul className="text-xs text-error/80 mt-1 space-y-1 list-disc pl-4">
          <li>Single 1600px image for all screen sizes</li>
          <li>Mobile downloads 4x more data than needed</li>
          <li>No <code>srcset</code> or <code>sizes</code> attributes</li>
          <li>Only JPEG format, no WebP/AVIF fallback</li>
          <li>Missing width/height attributes (causes CLS)</li>
        </ul>
      </div>
    </div>
  );
}
```

## Good — do this

`performance-responsive-images-good`

```tsx
export function ResponsiveImagesGood() {
  // In a real app, you'd have multiple image sizes generated at build time
  const baseUrl = 'https://images.pexels.com/photos/1181671/pexels-photo-1181671.jpeg?auto=compress&cs=tinysrgb';

  return (
    <div className="w-full max-w-md">
      <div className="bg-card border border-border rounded-lg overflow-hidden">
        {/* Responsive image with srcset and sizes */}
        <img
          src={`${baseUrl}&w=800`}
          srcSet={`
            ${baseUrl}&w=400 400w,
            ${baseUrl}&w=800 800w,
            ${baseUrl}&w=1200 1200w
          `}
          sizes="(max-width: 600px) 100vw, (max-width: 1024px) 50vw, 400px"
          alt="Developer working at a desk with multiple monitors showing code"
          className="w-full h-48 object-cover"
          width={800}
          height={533}
          loading="lazy"
          decoding="async"
        />
        <div className="p-4">
          <h3 className="font-semibold mb-2">Product Showcase</h3>
          <p className="text-sm text-muted-foreground">
            Browser selects optimal image size based on viewport and pixel density.
          </p>
        </div>
      </div>
      <div className="mt-4 p-3 bg-success/10 border border-success/30 rounded text-sm">
        <p className="font-medium text-success">Best Practices:</p>
        <ul className="text-xs text-success/80 mt-1 space-y-1 list-disc pl-4">
          <li><code>srcset</code> provides multiple image sizes</li>
          <li><code>sizes</code> tells browser expected display size</li>
          <li>Explicit <code>width</code>/<code>height</code> prevents CLS</li>
          <li>Use <code>&lt;picture&gt;</code> for WebP/AVIF with fallback</li>
          <li>Mobile gets ~100KB instead of ~400KB</li>
        </ul>
      </div>
    </div>
  );
}
```

## References

- [Serve responsive images](https://web.dev/articles/serve-responsive-images)
- [Use WebP images](https://web.dev/articles/serve-images-webp)
