Responsive Images: If you’re just changing resolutions, use srcset.

Avatar of Chris Coyier
Chris Coyier on (Updated on )

DigitalOcean provides cloud products for every stage of your journey. Get started with $200 in free credit!

If you’re implementing responsive images (different images in HTML for different situations) and all you are doing is switching between different versions of the same image (the vast majority of usage), all you need is the srcset attribute on the <img>. Gaze upon this easy syntax:

<img src="small.jpg" srcset="medium.jpg 1000w, large.jpg 2000w" alt="yah">

It’s not just the syntax that is easy, it does a better job than <picture> with <source>s with explicit media attributes (we’ll cover why in a moment). Plus it has the opportunity to be much better in the future with browser settings and browser improvements.

I’ve screencasted about this before, but it clicked better watching Mat Marquis’s talk at An Event Apart Austin and with Jason Grigsby’s post. I’m writing about it again here because I think it’s important for all of us to understand.

With srcset, the browser does the work of figuring out which image is best

In the simple example above, all we’re doing is telling the browser about some images that we have available and what size they are. The browser then does all the work figuring out which one will be best.

Mat Marquis demonstrated this by showing how the browser approaches it with math. Say you’re on a device with a screen width of 320px and is a 1x (non-retina) display. and the images you have are small.jpg (500px wide), medium.jpg (1000px wide), and large.jpg (2000px wide).

The browser goes:

Lemme do some quick math that nobody cares about except me.

500 / 320 = 1.5625
1000 / 320 = 3.125
2000 / 320 = 6.25

OK, so since I’m a 1x display, 1.5625 is the closest to what I need. It’s a little high, but it’s the best option compared to those other that are way too high.

Now another browser visits the site. It’s also a 320px display but it’s a retina (2x) display. That browser does the same math, only then goes:

OK, so since I’m a 2x display, I’m going to throw out that 1.5625 image because it’s too low for me and might look bad. I’m going to use the 3.125 image.

See how that’s already useful? You’re letting the browser do the work of figuring out what’s best for it rather than you trying to figure it out.

The browser is going to get smarter still

Remember there is already benefit to using srcset this way, but it’s going to get better yet. Think of srcset as suggestions or just extra information to help a browser decide. Ultimately it can do what it thinks is right. That means:

  • A browser could offer user preferences regarding images
  • A browser could start factoring in bandwidth

Yes, theoretical, but likely.

And if you go down the <picture> with explicit sources, the browser has to do exactly what you say and not make choices for itself. Now, <picture> can be set up such that it does exactly what srcset it going to do right now, it’s just a lot more verbose and doesn’t leave room for improvement.

Also, sizes

We didn’t talk about the sizes attribute at all here, on purpose. It’s actually not that bad to just leave it off. In that case, it assumes sizes="100vw", which is saying:

I assume that when you use an image, it’s going to be the entire width of the viewport.

That’s usually not an awful assumption to make.

If you want, you can get all kinds of specific about it. You can use sizes to match your CSS layout exactly and tell the browser exactly how big that image is going to be on every screen size, matching how your breakpoints work in your design. That can get a little complicated and honestly it might be a little dangerous because you’re putting CSS stuff in markup and you know how that goes. Eric Portis just wrote about this. Ideally it can be automated or injected server-side.

I also think kind of “generic” sizes attributes might be useful. On a kinda generic blog-ish site, maybe something like this is smart within content:

sizes="(min-width: 800px) 50vw, 100vw"

Meaning: “If the browser window is wider than 800px, this image is probably going to be displayed about half the size of that. If it’s smaller, it’ll probably be full-width.”

Why talk about this?

Again: the vast majority of responsive images use isn’t “art direction” based. Art direction is a fancy use case, and please do it to your heart’s content. <picture> is great at that.

Most responsive images uses will be: “I have multiple versions of this graphic. Here they are, use the right one.”

This is a very confusing subject. It needs to get thought about and written about so it can shake out and become a more ingrained part of our collective front end developer consciousness.

Tim Evko created a WordPress plugin for responsive images. It leverages WordPress’s ability to make smaller versions of images. Then you click the image you want, and it ultimately outputs the responsive images code needed for it. At the moment, it uses <picture>. That’s because <picture> is up in the collective front end developer consciousness in a much stronger way than srcset. Tim is trying to understand all this so he can figure out if and how to change that plugin.


This is tricky too.

If you want it right now and want great browser support, you need to polyfill it. But that has some potential downsides. So for now you’ll have to make that call for yourself, I’m not sure there is a best practice for all scenarios yet.