Responsive Images With srcset and sizes
Optimizing image delivery is crucial for web performance. Large, unoptimized images are a primary contributor to slow page loads, increased bandwidth…
Optimizing image delivery is crucial for web performance. Large, unoptimized images are a primary contributor to slow page loads, increased bandwidth consumption, and poor user experience, directly impacting metrics like Largest Contentful Paint (LCP) and Cumulative Layout Shift (CLS). This article details how to leverage the srcset and sizes attributes on the <img> tag, alongside the <picture> element, to serve appropriately sized and formatted images efficiently, ensuring responsiveness across diverse devices and network conditions.
The core principle is to provide the browser with a set of image candidates and enough information to intelligently select the most suitable one based on the current viewport, device pixel ratio, and network capabilities, without developer-side guesswork at runtime. This offloads decision-making to the browser, which has superior real-time context.
Understanding srcset and sizes
The srcset and sizes attributes work in conjunction on the <img> element to enable responsive image loading. Without these, browsers typically download a single image specified by the src attribute, often a large one, and then scale it down if necessary, wasting bandwidth and processing power.
The srcset Attribute
srcset provides a comma-separated list of image URLs, each accompanied by a "descriptor" indicating its intrinsic width or pixel density. This tells the browser about the available image versions.
- Width Descriptor (
w): This is generally preferred. It specifies the intrinsic width of the image file in pixels. For example,hero-800.jpg 800windicates thathero-800.jpgis 800 pixels wide. The browser uses this to determine which image best fits the layout width and device pixel ratio. - Pixel Density Descriptor (
x): Less flexible, this specifies the device pixel ratio for which the image is intended. For example,hero-2x.jpg 2xmeanshero-2x.jpgis suitable for 2x retina displays. If not combined withsizes, it's often used when the image's displayed width is fixed in CSS, and you only need to swap for higher-density screens.
Example srcset with width descriptors:
<img src="hero-fallback.jpg"
srcset="hero-400.jpg 400w,
hero-800.jpg 800w,
hero-1200.jpg 1200w,
hero-1600.jpg 1600w"
alt="A scenic landscape">
The src attribute here acts as a mandatory fallback for browsers that do not support srcset, though support is now nearly universal (Caniuse.com reports ~98% global support for srcset as of late 2023).
The sizes Attribute
The sizes attribute tells the browser how wide the image will be rendered on the screen at different viewport widths. This is crucial for the browser to make an informed decision when using srcset with width descriptors. It consists of a comma-separated list of media conditions and corresponding slot widths.
- Media Condition: A standard CSS media query (e.g.,
(max-width: 768px)). - Slot Width: The width the image will occupy when the media condition is met. This can be an absolute length (e.g.,
600px), a percentage of the viewport (e.g.,50vw), or a calculation (e.g.,calc(100vw - 32px)).
The browser evaluates the media conditions in order and picks the first one that matches. The final value (after the last media condition) acts as a default if no preceding condition matches. This default is often the width for larger screens.
Example sizes attribute:
<img src="hero-fallback.jpg"
srcset="hero-400.jpg 400w,
hero-800.jpg 800w,
hero-1200.jpg 1200w,
hero-1600.jpg 1600w"
sizes="(max-width: 600px) 100vw, /* Full viewport width on small screens */
(max-width: 1200px) 50vw, /* Half viewport width on medium screens */
800px" /* 800px wide on large screens by default */
alt="A scenic landscape">
In this example, if the viewport is 500px wide, the browser sees (max-width: 600px) 100vw and knows the image will occupy 500px. If the device has a 2x pixel ratio, it might request an image around 1000px wide from the srcset list (e.g., hero-1200.jpg). If the viewport is 1400px wide, no media condition matches, so it defaults to 800px and might request hero-800.jpg or hero-1200.jpg depending on DPR.
Serving Modern Formats with <picture>
While srcset and sizes handle resolution switching, the <picture> element addresses format switching. It allows you to specify multiple <source> elements, each with different media queries or image formats, and a fallback <img> tag.
The browser iterates through the <source> elements in the order they appear. For each <source>, it checks if its media attribute matches the current environment and/or if it supports the format specified in the type attribute. The first <source> that matches and whose format is supported by the browser is chosen, and its srcset (and optional sizes) attributes are used. If no <source> is matched or supported, the browser falls back to the inner <img> element.
Key Attributes for <source>
type: Specifies the MIME type of the image format (e.g.,image/avif,image/webp). This is critical for browser support detection.media: A media query, similar to CSS, allowing you to serve different images based on viewport characteristics (e.g.,(min-width: 768px)). This is less common for format switching but useful for art direction.srcset: Identical to thesrcseton<img>, providing image candidates for the specifiedtypeormedia.sizes: Identical to thesizeson<img>, used in conjunction withsrcset.
Example <picture> implementation:
<picture>
<!-- AVIF format for optimal compression and quality -->
<source type="image/avif"
srcset="hero-400.avif 400w,
hero-800.avif 800w,
hero-1200.avif 1200w,
hero-1600.avif 1600w"
sizes="(max-width: 768px) 100vw,
50vw">
<!-- WebP format for broader modern browser support -->
<source type="image/webp"
srcset="hero-400.webp 400w,
hero-800.webp 800w,
hero-1200.webp 1200w,
hero-1600.webp 1600w"
sizes="(max-width: 768px) 100vw,
50vw">
<!-- JPEG fallback for older browsers or unsupported formats -->
<img src="hero-800.jpg"
srcset="hero-400.jpg 400w,
hero-800.jpg 800w,
hero-1200.jpg 1200w,
hero-1600.jpg 1600w"
sizes="(max-width: 768px) 100vw,
50vw"
width="1600" height="900"
alt="A panoramic view of mountains at sunrise">
</picture>
In this structure, a browser supporting AVIF will load the AVIF version. If AVIF isn't supported but WebP is, the WebP version will be loaded. Otherwise, it falls back to the JPEG. Within each <source> (and the fallback <img>), srcset and sizes ensure the appropriately sized image is picked for that format.
Image Sizing and CLS Prevention
Crucially, always include width and height attributes (or use CSS aspect-ratio) on your <img> tag. These attributes tell the browser the intrinsic aspect ratio of the image. Even though the actual image downloaded might be different from the width/height specified (e.g., width="1600" height="900" might correspond to hero-1600.jpg, but hero-800.jpg is downloaded), the browser can reserve the correct amount of space in the layout before the image is fully loaded. This prevents Cumulative Layout Shift (CLS), a key Core Web Vitals metric, where content unexpectedly jumps around as images load and their dimensions become known.
For example, if hero-1600.jpg is 1600x900 pixels, then hero-800.jpg will be 800x450 pixels, both maintaining a 16:9 aspect ratio. Setting width="1600" height="900" on the <img> tag allows the browser to reserve a 16:9 space regardless of which version is downloaded.
Generating Responsive Images
Manually creating multiple image sizes and formats can be tedious. Several tools and services automate this process:
- Image CDNs (e.g., Cloudinary, Imgix, Akamai Image & Video Manager): These services can automatically transform, optimize, and serve images in various formats and sizes on-the-fly based on URL parameters or client hints. They also often integrate with Content Delivery Networks (CDNs) for faster delivery.
- Build Tools (e.g., Gulp, Webpack with plugins, Eleventy image plugin, Next.js Image Component): For static sites or sites with build processes, plugins can resize and convert images during the build step.
- Command-line tools (e.g., ImageMagick, libvips, FFmpeg for AVIF): For server-side processing or scripting, these tools offer fine-grained control over image manipulation.
When selecting sizes, common breakpoints or factors of 2 for device pixel ratios (e.g., 400w, 800w, 1200w, 1600w) are good starting points. Consider the maximum likely display width of your images and a few intermediate sizes. For formats, AVIF and WebP offer superior compression over JPEG/PNG and should be prioritized.
Trade-offs and Considerations
While the benefits are significant, there are minor trade-offs:
| Feature | Pros | Cons |
|---|---|---|
srcset/sizes |
Bandwidth savings, faster loads, improved LCP. Browser-optimized selection. | Requires generating multiple image sizes. More complex HTML. |
<picture> |
Modern format (AVIF/WebP) adoption with graceful fallbacks. Art direction capabilities. | Increases HTML verbosity. Requires multiple image formats. |
width/height attributes |
Prevents CLS, reserves layout space immediately. | Requires knowing image aspect ratio. May not be ideal if image aspect ratio changes with responsiveness (art direction). |
Common Pitfalls
- Incorrect
sizesattribute: A common mistake is to omitsizesor specify it incorrectly, especially when usingwdescriptors insrcset. Without accuratesizes, the browser defaults to100vw, which might lead to downloading larger images than necessary. Carefully map your CSS layout to thesizesattribute. - Missing
widthandheight: Forgetting these attributes (oraspect-ratioCSS) leads to CLS, negatively impacting user experience and Core Web Vitals scores. Always include them. srcattribute omission (for<img>or<picture>'s inner<img>): Thesrcattribute serves as a fallback for older browsers and is mandatory for the inner<img>within<picture>. Ensure it's present.- Incorrect order of
<source>elements: For<picture>, sources are evaluated top-down. Place newer, more efficient formats (like AVIF) first, followed by WebP, and finally the most compatible format (like JPEG/PNG) in the fallback<img>. - Over-optimizing image variants: While more variants offer finer control, diminishing returns apply. Generating too many small differences in size can increase storage and generation overhead for minimal performance gain.