#30DaysofHTML Day 28: < picture >, < source >, srcset, and sizes

Responsive images, retina images, and beyond

🎉📚 Get the #30DaysofHTML e-book📚🎉

Read on for details!

When Ethan Marcotte first described responsive design in 2010, he told us that it included a responsive grid layout, media queries, and images that resize. In 2010, the "images that resize" part of this was really hard. Typically it involved a server-side solution or a paid client-side solution to serve images depending on screen dimensions.

Fortunately, HTML has come to our rescue with the <picture> and <source> elements and the srcset and sizes attributes. <picture> and <source> are used for loading different images at different screen dimensions, with the browser loading only the image required so as to not impact site performance. srcset and sizes are used for choosing the image with the appropriate resolution for the device.

"Art direction:" <picture>

You include this image on your desktop page (photo by Snapwire from Pexels):

When it's on a phone, it looks like this:

Two problems here. First, we've downloaded a 160K image at mobile dimensions. Second, we can't see anything. Ugh.

The photo might be more effective if we crop it and show a smaller part of the photo at greater detail on mobile:

Now my image is 8K and you get way more detail on your phone than you do with that other image. Win-win! This is what people mean when they say "art direction." We're changing the photo in some way at different screen sizes for better communication of the message.

Swapping the images is easy. The code looks like this:

    <source srcset="balloons.jpg" media="(min-width: 1000px)">
    <img src="balloons-cropped.jpg" alt="Hot air balloons rise over the desert.">

The <picture> tag wraps around everything.

You may have as many <source> elements as you wish. If this looks familiar, that's because it's the same element used with <audio> and <video> (tomorrow!).

Each <source> element spells out a different image, via srcset, that should be loaded under different conditions spelled out in the media query, which is the value of the media attribute.

The <img> is a fallback for browsers that don't support <picture>. It's also the default image with the alt attribute. If no other images meet the <source> criteria, then <img> will load instead. Therefore, this is generally where you place your small, mobile image.

🖥 View this example in today’s CodePen demo.

Media queries FTW?

Use min-width or max-width media queries to swap images, just the same way you would in your CSS for swapping styles at breakpoints. This seems to work consistently across browsers.

However, other types of media queries may not work consistently. For example, here's one that swaps a color image for black and white when printed. This only works in Firefox. It would be awesome if it worked in Chrome and Safari, too.

  <source srcset="https://assets.codepen.io/296057/30dayshtml-balloons-bw.jpg" media="print">
  <img src="https://assets.codepen.io/296057/30dayshtml-balloons.jpg" />

Supporting new image formats for the web

You’ve probably heard about the new image formats for the web like WebP and AVIF, among others. You probably have (appropriate!) hesitations about using these in your site designs because of concerns about backwards compatibility.

<picture> is good for this as well, as described in this example from MDN:

  <source srcset="logo.webp" type="image/webp">
  <img src="logo.png" alt="logo">

Just as you saw above, the browser will find the image that it supports and display that image. If the browser supports WebP, that’s what it will display. Otherwise, it will go to the PNG format.

Switching Resolutions with srcset and sizes

You may want to load high-resolution images on devices that support this and have the bandwidth to load them quickly.

While you can do this with the <picture> element and media queries, the srcset attribute may be used without <picture> to make this work.

Eric Portis has an amazing illustrated article explaining why srcset and sizes are the right tool for the job. There is nothing we can add to this. Please go read it; it's a masterpiece.

🎉📚Get the #30DaysofHTML e-book📚🎉

We are super excited to announce our e-book!

Email is great, and blogs are awesome, but it can be challenging to use them as a reference in the future. We'll be assembling this month's work into an e-book. Would you like a copy?

☕️ If you are financially able to do so, buy us a coffee (or two, or five!). Coffees are $5 each, and the e-book starts at $6 (and will go up from there).

  • 🎉 If you already bought us a coffee, you get an e-book! 😁 🎉

👍 Or spread the word and we'll give you a free e-book! Choose one of these below:

  • Mention and link to at least one post from #30DaysofHTML in your newsletter by April 30. (If you’ve already done this, you get a free e-book!)

  • Retweet this e-book announcement, or talk about the e-book on other social media platforms, by April 30!

We will assemble the e-book from these past posts and emails and get that out to you as soon as possible. We anticipate it will be no later than June 30.

<picture> and <source> demo

🖥 View the <picture> and <source> demo on CodePen.

View the CodePen demo

Challenge: <picture> and <source>

👩🏽‍💻 Try today’s CodePen Challenge about <map> and <area>. When you’ve completed it, post your answer in our discussion in Substack.

Take the CodePen Challenge

More information and examples

📚 MDN: <picture> and <source>

📚 WHATWG: <picture> and <source>

📚 Eric Portis: Srcset and sizes

📚 CSS-Tricks: A Guide to the Responsive Images Syntax in HTML

📚 MDN: Responsive images tutorial