Responsive Images: Providing Optimal Images for Different Devices
In a coffee shop, you'll notice the same coffee comes in different cup sizes—small, medium, large. Customers can choose the portion size that suits their needs, avoiding waste or shortage. Responsive images follow a similar philosophy: provide different versions of images for different devices and screens, ensuring both display quality and avoiding bandwidth waste.
Why Do We Need Responsive Images?
In early responsive design, developers would typically use one high-resolution large image and then scale it with CSS for different sizes. This approach seems simple but has serious problems:
Suppose you have a 2400×1600 pixel, 500KB high-definition image. When users access with a mobile phone (screen width only 375px), the browser still downloads the complete 500KB image and then scales it down. This means:
- Wasted bandwidth: Mobile users download far more data than they actually need
- Slow loading: Large images significantly slow down page loading on mobile networks
- Battery consumption: Downloading and processing large images consumes more power
Responsive image technology allows browsers to intelligently choose the most appropriate image version—loading small images on phones and large, high-definition images on high-definition large screens—achieving "on-demand supply."
srcset Attribute: Resolution Switching
srcset is the most fundamental tool for implementing responsive images, allowing you to provide multiple image sources for browsers to choose the most appropriate one based on device characteristics.
Pixel Density-based Selection
The first use case is providing different image versions for different pixel densities:
<img
src="hero-1x.jpg"
srcset="hero-1x.jpg 1x, hero-2x.jpg 2x, hero-3x.jpg 3x"
alt="Hero banner image"
/>The meaning of this code is:
src="hero-1x.jpg": This is the fallback solution, used when browsers don't supportsrcsethero-1x.jpg 1x: Standard screen (1x pixel density) uses this versionhero-2x.jpg 2x: High-definition screen (2x pixel density, like iPhone Retina) uses this versionhero-3x.jpg 3x: Ultra-high-definition screen (3x pixel density, like some Android flagship phones) uses this version
When users access with an iPhone 13 (2x screen), the browser will automatically select hero-2x.jpg. If they're using a regular laptop (1x screen), it will load hero-1x.jpg. This ensures each device sees clear images while avoiding unnecessary bandwidth waste.
Actual Width-based Selection
A more common scenario is providing different versions based on the actual display width of the image:
<img
src="photo-800.jpg"
srcset="
photo-400.jpg 400w,
photo-800.jpg 800w,
photo-1200.jpg 1200w,
photo-1600.jpg 1600w
"
alt="Beautiful landscape"
/>Here w represents the actual width of the image (in pixels):
photo-400.jpg 400w: This image is 400 pixels widephoto-800.jpg 800w: This image is 800 pixels widephoto-1200.jpg 1200w: This image is 1200 pixels widephoto-1600.jpg 1600w: This image is 1600 pixels wide
The browser makes a comprehensive decision based on viewport size, the image's display size on the page, and device pixel ratio to select the most appropriate image. For example:
- On a 375px wide phone, it might load the 400w or 800w version
- On a 1920px wide desktop monitor, it might load the 1600w version
- On a 2x Retina screen iPad, it will choose a larger version to ensure clarity
sizes Attribute: Telling the Browser Display Size
When using srcset alone, browsers only know the actual widths of each image but not how much space the image will occupy on the page. The sizes attribute tells the browser the display size of the image under different viewport widths.
Basic Usage
<img
src="product-800.jpg"
srcset="product-400.jpg 400w, product-800.jpg 800w, product-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw,
(max-width: 1200px) 50vw,
400px"
alt="Product showcase"
/>The value of the sizes attribute is a series of media conditions and corresponding display widths:
(max-width: 600px) 100vw: When viewport width ≤ 600px, image occupies 100% viewport width(max-width: 1200px) 50vw: When viewport width ≤ 1200px, image occupies 50% viewport width400px: In other cases (viewport width > 1200px), image displays at 400px width
Let's look at a practical example:
Assume a user accesses with a 1440px wide, 2x pixel density MacBook Pro. According to the sizes rules, the image will display at 400px wide. Since the screen is 2x density, the browser actually needs an 800px wide image resource (400 × 2 = 800). Therefore, the browser will select product-800.jpg from the srcset.
If using a 375px wide, 3x pixel density iPhone, according to the first rule, the image will occupy 100vw, which is 375px. Since it's a 3x screen, the browser needs a 1125px wide image (375 × 3 = 1125), so it will select product-1200.jpg.
Complex Layout Example
In responsive grid layouts, the sizes attribute is particularly useful:
<img
src="gallery-800.jpg"
srcset="
gallery-400.jpg 400w,
gallery-800.jpg 800w,
gallery-1200.jpg 1200w,
gallery-1600.jpg 1600w
"
sizes="(max-width: 599px) 100vw,
(max-width: 899px) 50vw,
(max-width: 1199px) 33.33vw,
25vw"
alt="Gallery image"
/>This configuration applies to responsive image galleries:
- Mobile (< 600px): 1 column layout, each image takes 100% width
- Tablet portrait (600-899px): 2 column layout, each image takes 50% width
- Tablet landscape (900-1199px): 3 column layout, each image takes 33.33% width
- Desktop (≥ 1200px): 4 column layout, each image takes 25% width
The browser will precisely calculate the required image size based on this information and select the optimal resource.
picture Element: Art Direction
Sometimes, just scaling image sizes isn't enough. On different devices, you might want to use completely different image compositions—this is "Art Direction." The <picture> element is specifically designed to solve this problem.
Art Direction Basics
<picture>
<source media="(max-width: 599px)" srcset="banner-mobile.jpg" />
<source media="(min-width: 600px)" srcset="banner-desktop.jpg" />
<img src="banner-desktop.jpg" alt="Company banner" />
</picture>In this example:
- Mobile (< 600px) loads
banner-mobile.jpg, possibly a portrait crop or more compact composition - Desktop (≥ 600px) loads
banner-desktop.jpg, possibly a landscape composition with more background elements - The
<img>tag is required, serving both as fallback and definingalttext
This is not just a size change, but a completely different image. For example, the desktop banner might show the entire team in a wide scene, while the mobile version might focus on a single person's close-up for better clarity and impact on small screens.
Combining srcset for Complete Solution
<picture> can be combined with srcset to handle both art direction and resolution switching:
<picture>
<!-- Mobile: portrait composition + multiple resolutions -->
<source
media="(max-width: 599px)"
srcset="hero-mobile-400.jpg 400w, hero-mobile-800.jpg 800w"
sizes="100vw"
/>
<!-- Tablet: square composition + multiple resolutions -->
<source
media="(min-width: 600px) and (max-width: 1199px)"
srcset="hero-tablet-800.jpg 800w, hero-tablet-1200.jpg 1200w"
sizes="100vw"
/>
<!-- Desktop: landscape composition + multiple resolutions -->
<source
media="(min-width: 1200px)"
srcset="
hero-desktop-1200.jpg 1200w,
hero-desktop-1600.jpg 1600w,
hero-desktop-2400.jpg 2400w
"
sizes="100vw"
/>
<!-- Fallback -->
<img src="hero-desktop-1200.jpg" alt="Hero image" />
</picture>The browser will check each <source>'s media condition in order and use the first matching one, then select a specific image file based on that <source>'s srcset and sizes. This achieves:
- Different compositions for different screen sizes
- Optimal image selection for the same composition
- Perfect balance between display quality and performance
Modern Image Format Support
The <picture> element can also be used to provide modern image formats while maintaining backward compatibility:
<picture>
<!-- Prioritize AVIF format (smallest file size) -->
<source srcset="photo.avif" type="image/avif" />
<!-- If AVIF not supported, try WebP -->
<source srcset="photo.webp" type="image/webp" />
<!-- Fallback: traditional JPEG -->
<img src="photo.jpg" alt="Beautiful photo" />
</picture>The browser will check in order:
- Does it support AVIF? If yes, use
photo.avif(possibly only 50KB) - Doesn't support AVIF, does it support WebP? If yes, use
photo.webp(possibly 80KB) - Neither supported, use traditional JPEG
photo.jpg(possibly 150KB)
Modern browsers (like Chrome, Firefox) will load AVIF or WebP for smaller file sizes and faster loading. Old browsers (like IE11) will fall back to JPEG, ensuring compatibility.
Combining Formats and Resolutions
You can also combine format selection with resolution switching:
<picture>
<!-- WebP format + multiple resolutions -->
<source
type="image/webp"
srcset="photo-400.webp 400w, photo-800.webp 800w, photo-1200.webp 1200w"
sizes="(max-width: 600px) 100vw, 800px"
/>
<!-- JPEG fallback + multiple resolutions -->
<source
srcset="photo-400.jpg 400w, photo-800.jpg 800w, photo-1200.jpg 1200w"
sizes="(max-width: 600px) 100vw, 800px"
/>
<img src="photo-800.jpg" alt="Photo description" />
</picture>Responsive Images in CSS
Although HTML provides powerful responsive image functionality, sometimes you need to handle background images in CSS. You can use media queries to achieve similar effects:
.hero {
background-image: url("hero-mobile.jpg");
background-size: cover;
background-position: center;
}
/* Tablet */
@media (min-width: 600px) {
.hero {
background-image: url("hero-tablet.jpg");
}
}
/* Desktop */
@media (min-width: 1200px) {
.hero {
background-image: url("hero-desktop.jpg");
}
}
/* High-definition screen */
@media (min-width: 1200px) and (min-resolution: 2dppx) {
.hero {
background-image: url("hero-desktop-2x.jpg");
}
}A more modern approach is to use the image-set() function:
.hero {
background-image: image-set(
url("hero.jpg") 1x,
url("hero-2x.jpg") 2x,
url("hero.webp") 1x type("image/webp"),
url("hero-2x.webp") 2x type("image/webp")
);
}The browser will automatically select the most appropriate image format and resolution version.
Practical Application Scenarios
Product List Page
In e-commerce website product lists, responsive images are crucial:
<!-- Product thumbnails -->
<picture>
<source
media="(max-width: 599px)"
srcset="product-thumb-300.webp 1x, product-thumb-600.webp 2x"
type="image/webp"
/>
<source
media="(max-width: 599px)"
srcset="product-thumb-300.jpg 1x, product-thumb-600.jpg 2x"
/>
<source
srcset="product-thumb-400.webp 1x, product-thumb-800.webp 2x"
type="image/webp"
/>
<source srcset="product-thumb-400.jpg 1x, product-thumb-800.jpg 2x" />
<img src="product-thumb-400.jpg" alt="Wireless headphones" />
</picture>On mobile, load 300px wide small images (or 2x screen uses 600px), while on desktop load 400px images, prioritizing WebP format to save bandwidth.
Article Header Image
Blog article header images often need art direction:
<picture>
<!-- Mobile: 1:1 crop -->
<source
media="(max-width: 767px)"
srcset="article-hero-square-400.jpg 400w, article-hero-square-800.jpg 800w"
sizes="100vw"
/>
<!-- Desktop: 16:9 crop -->
<source
media="(min-width: 768px)"
srcset="
article-hero-wide-800.jpg 800w,
article-hero-wide-1200.jpg 1200w,
article-hero-wide-1600.jpg 1600w
"
sizes="100vw"
/>
<img
src="article-hero-wide-1200.jpg"
alt="Understanding responsive images"
loading="lazy"
/>
</picture>Note the addition of loading="lazy", which is the browser's native lazy loading feature for further performance optimization.
Performance Optimization Tips
1. Lazy Loading
For images outside the first screen, use lazy loading to significantly improve initial loading speed:
<img
src="photo.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w"
sizes="(max-width: 600px) 100vw, 50vw"
loading="lazy"
alt="Gallery photo"
/>The browser will delay loading this image until the user scrolls close to its position.
2. Preload Critical Images
For critical first-screen images (like hero banners), you can use preload to prompt the browser to load them early:
<link
rel="preload"
as="image"
href="hero-1200.jpg"
imagesrcset="hero-400.jpg 400w, hero-800.jpg 800w, hero-1200.jpg 1200w"
imagesizes="100vw"
/>This will make the browser start downloading images early, improving first-screen rendering speed.
3. Define Aspect Ratios to Avoid Layout Shift
Setting aspect ratios for images prevents layout jumping during loading (CLS):
<img
src="photo.jpg"
srcset="photo-400.jpg 400w, photo-800.jpg 800w"
sizes="(max-width: 600px) 100vw, 800px"
width="800"
height="600"
alt="Photo"
/>Even before the image loads, the browser will reserve the correct space based on width and height.
Or use CSS:
.image-container {
aspect-ratio: 16 / 9; /* Modern method */
}
/* Fallback for older browsers */
.image-container {
position: relative;
padding-bottom: 56.25%; /* 9/16 = 0.5625 */
}
.image-container img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
}Common Problems and Best Practices
Problem 1: Too many image versions are troublesome to prepare
Indeed, manually creating multiple versions is tedious. In actual development, automated tools are typically used:
- Build tools: Use Webpack, Vite's image processing plugins to automatically generate multiple sizes
- Image CDNs: Use services like Cloudinary, imgix to dynamically generate different versions via URL parameters
- CMS systems: WordPress, Next.js and other frameworks have built-in image optimization features
For example, using imgix, you only need to upload one high-definition original:
<img
src="https://example.imgix.net/photo.jpg?w=800"
srcset="
https://example.imgix.net/photo.jpg?w=400 400w,
https://example.imgix.net/photo.jpg?w=800 800w,
https://example.imgix.net/photo.jpg?w=1200 1200w
"
sizes="(max-width: 600px) 100vw, 800px"
alt="Photo"
/>The CDN will generate the required sizes in real-time, greatly simplifying the workflow.
Problem 2: How to determine which sizes are needed?
Analyze your website traffic and common devices:
Common breakpoints and corresponding image widths:
- Mobile (320-599px): 320w, 480w
- Tablet (600-1199px): 600w, 800w, 1024w
- Desktop (1200px+): 1200w, 1600w, 1920wUsually preparing 3-5 sizes is enough to cover most scenarios. Too many options increase complexity instead.
Problem 3: Browser support situation
Modern responsive image features have excellent browser support:
srcsetandsizes: Supported by all modern browsers (except IE)<picture>element: Chrome 38+, Firefox 38+, Safari 9.1+, Edge 13+- For unsupported browsers, they fall back to the
<img>tag'ssrcattribute
If you need to support IE, ensure appropriate src fallback solutions.
Best Practice Summary
Always provide alt text: This is important for both accessibility and SEO
Mobile-first image preparation: First ensure mobile experience is good, then enhance desktop
Use modern formats: WebP or AVIF are typically 25-50% smaller than JPEG
Use lazy loading appropriately: Images outside the first screen should be lazy loaded
Monitor actual performance: Use Chrome DevTools' Network panel to check actual downloaded image sizes
Define sizes to avoid layout shift: Use
width/heightattributes or CSSaspect-ratio
Summary
Responsive images are an essential skill in modern web development. By properly using srcset, sizes, and <picture> elements, you can:
- Improve performance: Users only download the image sizes they actually need
- Save bandwidth: Especially important in mobile network environments
- Enhance experience: See clear, appropriate images on any device
- Optimize SEO: Faster loading speeds directly impact search rankings
Remember the key points:
- Use
srcsetto provide multiple resolution versions - Use
sizesto tell the browser the image's display size - Use
<picture>to implement art direction and format selection - Combine lazy loading and modern image formats for further optimization
Mastering responsive image technology will elevate your website to new levels in both performance and visual quality.