Responsive Images

Difficulty: Intermediate

Responsive images ensure that users download appropriately sized images for their device, saving bandwidth on mobile while delivering sharp visuals on high-resolution screens. Without responsive images, a mobile user on a 375px-wide screen downloads the same 2000px-wide image that a desktop user sees, wasting data and slowing page load. The HTML srcset and sizes attributes, the <picture> element, and CSS object-fit together provide a complete toolkit for responsive image handling.

The srcset attribute on an <img> tag provides the browser with a list of image sources at different widths or pixel densities. Using width descriptors (e.g., srcset="small.jpg 400w, medium.jpg 800w, large.jpg 1200w"), you tell the browser the intrinsic width of each image. The browser then combines this with the sizes attribute and the viewport width to choose the most appropriate source. The sizes attribute tells the browser how large the image will be displayed: sizes="(min-width: 1024px) 33vw, (min-width: 640px) 50vw, 100vw" means the image occupies 33% of the viewport on desktop, 50% on tablet, and 100% on mobile.

For pixel density switching (serving 2x images on Retina screens), use density descriptors: srcset="logo.png 1x, logo@2x.png 2x, logo@3x.png 3x". The browser selects the source matching the device's pixel ratio. This is simpler than width descriptors but less flexible - it does not account for the image's display size.

The <picture> element enables art direction - serving entirely different images based on conditions. Unlike srcset (which lets the browser choose), <picture> gives you explicit control. Use <source> elements with media attributes to specify conditions: a wide landscape photo for desktop, a cropped portrait version for mobile. The browser uses the first matching source and falls back to the <img> element if none match.

CSS object-fit controls how an image fills its container, similar to background-size for background images. object-fit: cover scales the image to fill the container while maintaining aspect ratio (cropping edges if needed). object-fit: contain scales the image to fit entirely within the container (may leave empty space). object-fit: fill stretches the image to fill the container (distorts aspect ratio). Combined with a fixed-size container, object-fit ensures images look good regardless of their original dimensions.

Code examples

srcset with Width Descriptors and sizes

<!-- Browser chooses the best image based on viewport + sizes -->
<img
  src="image-800.jpg"
  srcset="
    image-400.jpg   400w,
    image-800.jpg   800w,
    image-1200.jpg 1200w,
    image-1600.jpg 1600w
  "
  sizes="
    (min-width: 1024px) 33vw,
    (min-width: 640px) 50vw,
    100vw
  "
  alt="A scenic mountain landscape"
  loading="lazy"
  decoding="async"
>

<!-- How the browser decides:
  1. Reads sizes to determine display width (e.g., 33vw on 1200px screen = 400px)
  2. Multiplies by device pixel ratio (e.g., 400px * 2 = 800px on Retina)
  3. Chooses the closest srcset image (image-800.jpg)
-->

srcset lists available image widths (400w, 800w, etc.). sizes tells the browser the display size at each breakpoint. The browser does the math: display width * pixel ratio = needed image width, then picks the closest match from srcset.

Pixel Density Descriptors

<!-- Simple 1x/2x/3x for logos and icons -->
<img
  src="logo.png"
  srcset="
    logo.png    1x,
    logo@2x.png 2x,
    logo@3x.png 3x
  "
  alt="Company logo"
  width="200"
  height="60"
>

<!-- Profile avatar with density switching -->
<img
  src="avatar-100.jpg"
  srcset="
    avatar-100.jpg 1x,
    avatar-200.jpg 2x
  "
  alt="User avatar"
  width="100"
  height="100"
  style="border-radius: 50%;"
>

Density descriptors (1x, 2x, 3x) are simpler than width descriptors. The browser matches the device's pixel ratio to the right source. Use this for fixed-size images (logos, icons, avatars) where the display size does not change.

Art Direction with picture Element

<!-- Different crops for different screen sizes -->
<picture>
  <!-- Wide landscape for desktop -->
  <source
    media="(min-width: 1024px)"
    srcset="hero-wide.jpg"
  >
  <!-- Medium crop for tablet -->
  <source
    media="(min-width: 640px)"
    srcset="hero-medium.jpg"
  >
  <!-- Tight portrait crop for mobile -->
  <img
    src="hero-mobile.jpg"
    alt="Hero image showing the product in use"
    loading="lazy"
  >
</picture>

<!-- Format switching: serve modern formats with fallback -->
<picture>
  <source type="image/avif" srcset="photo.avif">
  <source type="image/webp" srcset="photo.webp">
  <img src="photo.jpg" alt="Product photo" loading="lazy">
</picture>

The picture element gives explicit control over which image loads. Use media attributes for art direction (different crops per screen size). Use type attributes for format switching (AVIF > WebP > JPEG). The img is the fallback.

CSS object-fit for Image Containers

<style>
  .card-image {
    width: 100%;
    height: 200px;
    overflow: hidden;
  }
  /* Cover: fill container, crop excess */
  .card-image img.cover {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
  }
  /* Contain: fit inside, may show background */
  .card-image img.contain {
    width: 100%;
    height: 100%;
    object-fit: contain;
    background: #f1f5f9;
  }

  /* Avatar: always a circle, always cropped well */
  .avatar {
    width: 80px;
    height: 80px;
    border-radius: 50%;
    object-fit: cover;
    object-position: top; /* Focus on face */
  }

  /* Full-width hero with aspect ratio */
  .hero-image {
    width: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
  }
</style>

<div class="card-image">
  <img class="cover" src="photo.jpg" alt="Product">
</div>

<img class="avatar" src="person.jpg" alt="User photo">

<img class="hero-image" src="banner.jpg" alt="Hero banner">

object-fit: cover fills the container and crops excess (like background-size: cover). object-fit: contain fits the entire image inside the container. object-position controls the focal point. aspect-ratio maintains proportions without fixed height.

Key points

Concepts covered

srcset, sizes, picture Element, object-fit, Art Direction, Resolution Switching