Responsive Image with picture
Serving the right image at the right size saves bandwidth on phones and avoids blurry assets on retina displays. The `<picture>` element plus `srcset` lets the browser pick the best source for the device. This snippet covers density-based srcset for retina, width-based srcset with sizes for fluid layouts, and art direction with multiple `<source>` entries for different aspect ratios.
995 views
5
<img
src="/avatar.png"
srcset="/avatar.png 1x, /[email protected] 2x, /[email protected] 3x"
alt="User avatar"
width="40"
height="40"
>The 1x / 2x / 3x form tells the browser which file to load at each device pixel ratio. The browser picks the smallest image that meets or exceeds the screen density, so a phone with devicePixelRatio: 2 downloads [email protected] instead of the 3x version. Always include explicit width and height so the browser reserves space before the image loads (this prevents layout shift). The 1x entry is also the src for browsers that do not support srcset, so the fallback is automatic.
<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, 800px"
alt="Sunset over the city"
width="800"
height="450"
>The width-based form is correct when the rendered size depends on viewport width (a hero image, a card cover). The srcset lists candidate files with their natural widths, and sizes describes how wide the image will be at each breakpoint. The browser combines viewport width plus density and picks the closest candidate. This single tag replaces a stack of media queries and gives the browser, not the developer, the final say on which file is best.
<picture>
<source
media="(min-width: 1024px)"
srcset="/landscape-1600.jpg 1x, /landscape-3200.jpg 2x"
>
<source
media="(min-width: 600px)"
srcset="/landscape-800.jpg 1x, /landscape-1600.jpg 2x"
>
<img
src="/portrait-600.jpg"
srcset="/portrait-600.jpg 1x, /portrait-1200.jpg 2x"
alt="Mountain ridge"
width="600"
height="800"
>
</picture>When the picture itself should change (a wide landscape crop on desktop, a tight portrait crop on mobile), srcset alone is not enough; the image needs different art at different sizes. <picture> lets you list <source> elements with media queries and falls back to the inner <img> when none match. The browser picks the first <source> whose media matches, then applies the same density logic to its srcset. This pattern is the right answer for hero images that need cropped variants per breakpoint.
