#133: Figuring Out Responsive Images

I'm probably a bit rare in that I rather enjoyed trying to keep up on the responsive images thing. It's an interesting problem that bred lots of interesting solutions. The whole thing is starting to wrap up now though, now that the official solutions are:

<picture> and friends

<img> with srcset and sizes

The problem is: I don't really get it. I thought the original picturefill was pretty simple. List a bunch of sources with media queries. First one to match, that's the one that gets used. That made sense to me. This new stuff is a bit different. Solvable problem! Just like everything else, I need to figure it out.

That's why I was totally sympathetic to Martin Wolf's post "The new srcset and sizes explained" where he was struggling with the same problem. So I used that as a starting point for playing myself.

Here's some things I've learned.

This part makes sense I think:

And this is where it gets weird:

Why are we telling the browser how big an image is? It's a browser. Shouldn't it know how big images are? Well it does, but only after it downloads the entire thing. Smarter decisions can be made right off the bat if it knows this information sooner. So we just tell it. You could lie. Or be wrong. Which is weird but whatever.

Now that you have those different image options listed, you'll need to also use the sizes attribute. This provides more information to the browser about what how to intend to display the image so it can use that in making a choice about which.

The sizes attribute is also weird to me:

Again, it's all about intention. The sizes attribute doesn't actually have any effect on the size the image actually renders. (I was wrong about that in the video.) That's left to the real actual image size itself, or (more likely) CSS. We're just giving the browser information about what we intend to do so that it can make a smart choice about which image to use. I think it feels weird because we could again, lie, or be wrong, which is unusual thing in HTML.

If we provide all this info, and do it right, then the browser (or the polyfill) can make a smart choice about what image to display.

Say we're on a 1x screen. Because we've told the browser we're going to be using these images as big as we possibly can (100% of the viewport), the "breakpoints" for when the browser will flip out the images will happen at 1280px, 640px, and 320px, the same exact sizes as we've told it the images are.

If we're on a 2x screen, those "breakpoints" will cut in half (regardless of what we actually do to size those images) and will be at 640px, 320px, and 160px.

Now let's say we use the same images, but we know a lot more about our page layout, and used something like this:

On a 1x screen, you'll always get the 320w (small) image when the viewport is 500px wide or smaller, and you'll always get the 640w (medium) image when the viewport is larger. You'll never get the large image, because it can tell you'll never need that many pixels.

Ona 2x screen, you'll always get the 640w (medium) image when the viewport is 500px wide or smaller (because it thinks it needs 500px of pixels and the small isn't enough at 320px), and you'll always get the 1280w (large) image when the viewport is larger. You'll never get the small image, because it's never enough pixels to cover what you've told it you intend to render the image at.

Actual Sizing

Remember the actual sizing of the image is still up to you. I would think in the majority of cases it's you doing it through the CSS. And the CSS always wins. What you declare there will be the rendered width of the image no matter what happens with the srcset and sizes stuff. That just works out which image will be shown.

This is what makes the sizes attribute a bit tough. Let's say you have something like:

That's not unusual at all. So now what size do you use in the sizes attribute? That would be 13.33% (multiply them all together) because that number needs to be relative to the viewport, not the container. And that doesn't take into account margins and padding and stuff on those containers, so it's kind of a guess. I guess close counts in horseshoes, hand grenades, and the sizes attribute.

Then let's say a media query comes along and the body actually becomes 75% wide on top of all that. You need to know that so you can adjust what you think the rendered size of the images will be. Your sizes attribute might become:

sizes="(min-width: 500px) 8%, 13.33%"

Then go through that again for every layout media query you have that affects content images. It can get a bit complex.

Practical Sizes?

Assuming that content images will be around half the size of the browser window on large screens and the full size of the browser window on small screens - just let the breakpoints happen where they happen. You'll still get a pretty decent choice this way without slaving away over matching all your media queries exactly.

And remember these are content images. HTML tends to last longer than CSS or JS does, especially when it's content.

Other Things To Know

You can also specify if an image is 2x or 1x with srcset. So a really simple use case can be:

That alone is pretty useful. Don't mix it with specifying widths. As Eric Portis says:

And again let me emphasize that while you can attach 1x/2x resolution descriptors to sources in srcset instead of w descriptors, 1x/2x & w do not mix. Don’t use both in the same srcset. Really.

And remember when I said the original picturefill was easy? The new <picture> can be that easy, but the <source> elements inside <picture> also support srcset and sizes. That means you can get very specific. It adds another layer to this:

You decide which gets displayed based on media queries

That has it's own srcset/sizes, for determining exactly which src gets used

Comments

This is some great progress with the spec finally being implemented.
I guess I’m kind of more curious in how CMS’s will allow for it to be utilised and as to whether clients will grasp the idea.
Least i know that I can start using this stuff on my recent projects with the polyfill.

Hadn’t heard about srcset until now but it looks great. Plus, I can take still use this on client projects by letting the CMS take control of creating/ loading multiple versions of their image. Awesome!

I’ve seen a few people now who think that sizes effects, rather than reflects, the size of the image. It is kinda weird that it doesn’t.

But I’d rather describe the problem to the browser than prescribe a solution (which is what attatching media queries to sources directly does). Relates to this bit of Jeremy Keith’s recent “Seams” article:

We’re constantly faced with challenges like dealing with users on slow networks or small screens. So we try to come up with solutions (bandwidth media queries, responsive images) that have at their heart an assumption that we know better than the end user what they should get.

The browser dosen’t know either the source sizes or the destination layout size when it needs to pick a source, because of preloading. So we just tell it, and let it make the best decision for the user, given everything that it does know (e.g., the user’s bandwidth, a user-settable preference, their device-pixel-ratio, or whatever).

If we need to prescribe specific sources for specific breakpoints, we can step in and take control with picture and source media.

Yoav’s Responsive Image Container idea would make this all much simpler. srcsetw information gets encoded in the file itself in a header; the browser preloads that header and a base image but only loads the bytes it needs to “upgrade” it to the destination layout size after it has loaded CSS and figured that layout size out for itself, so we don’t need sizes… but it’s a long way off.

One nit with the examples: % is no longer valid in sizes; it was depreciated in favor of vw to make it clear that you’re talking about a percentage of the viewport width, not the parent element.

Great overview Chris (following on from Erics’ overview on his own site and Smashing recently).

I can feel new brain synapses developing with each pass over these articles and each new codepen. Hoping to have a list of patterns for this as part of going over it time and time again, if you’re working on something similar give me a shout and I’ll send my stuff through.

The <picture> element and the srcset attributes are currently not supported by any browsers without the help of a polyfill. The Picturefill polyfill included in the list of links at the end will enable both features in most browsers. The Picturefill website has more detailed documentation about browser support.

Now that the spec is being nailed down, it is likely that the major browsers will begin supporting it natively in the near future.

Great walkthrough! Only on question left: If we provide the browser with detailed “sizes”-info (max/min-widths + relative widths)—would there be no or little use for “2x” in srcset? Does this solution handle resolution when picking images, even without the 2x-thing?

Not particularly current nor maybe even relevant to this thread, but I’ve been using the code below for a few years and get the desired results ( in this case responsive bg images)
In the WP header file

I want to use it on eshop with one simply rule – display low-res images on mobile phones and better quality ones on desktop. I asume that with doing this, i could save quite a lot of data trafic for mobile users so as a sideeffect increase for them the speed of the web. I know that mobile phones now got sometimes very high resolution, so i would like to target lowress displays the low resolution displays or higher with some multiplier. And i would like to do it with shortest possible html code with only 2 img versions (btw i heard that e.g. jpg with compression lvl 60 resized to 50 % is nicer and data-smaller, then nonresized quality 90 jpg) and with good enough compatibility (most used android, ios, winphone mobile browsers). What code would you reccomend?

I am confused.com (have to read again … and again)
It all looks like a load more ruddy work (trail / error / trial) to me … and trying to explain that to clients ?!!?!?!
I am old school, brought-up on penny-pinching bandwidth and 48K Dial-ups … every pixel, character and byte was squeezed out of HTML/CSS/Script … now it’s BLOATSVILLE !! Especially ruddy WordPress which already hogs TB of used server space/ creates unused images litke there is no tomorrow and 1000’s of php files to serve a few ruddy pages!

Hi,
I’m just wondering, If I want to use srcset I must have picture with different size as example :
I want to use srcset for my image named ‘pic.jpg’ it had 1280×1024 px, If I want to use it for I pad, I must re-size it ( to Ipad dimension) and save it ‘ipad.jpg’ and so on for all screens ?? Or just one picture and the srcset will do the other?? Because to me is better to use one picture in my ‘Media folder’ and give it a style in Css file to re-size it based on screen device than use 3 or 4 pictures and give it a style in my Css file

This article is great, but in my humble opinion i think you should educate your readers about browsers that don’t support the srcset attribute. People shouldn’t only know how to use this technology but also how they would write a fallback for older browsers which achieves the exact same effect.

This is pretty cool stuff! Seems simple, elegant and quite frankly very useful. I haven’t had time to play around w/ it yet but it’s on my to do list. I am curious if there have been any issues on mobile platforms or if that too is seem-less and supported???

Are you trying to resize the area smaller and expecting to see the larger image get swapped out by the smaller one?

If so, that’s not how it works anymore. Spec change I think, and Picturefill updated to match. If the browser already has the larger image it won’t swap it out for a smaller one (because why would it, it’s more efficient not to).

I’ve often had to use background image options in order to manage images, and generally the images that pose the biggest problems are photos that are full page photos that have to be laid out in different orientations, and it mobile and have a focal point in the photo (such as a person’s face). Getting the photo to line up consistently and scale is really impossible. Which then requires 3 to 12 different size images. This is why most people use a generic photo in the background with a single button in the middle. Because it doesn’t matter how the photo is laid out.

We have a pretty good* newsletter.

Email Address

CSS-Tricks* is created, written by, and maintained by Chris Coyier and a team of swell people. It is built on WordPress, hosted by Media Temple, and the assets are served by MaxCDN. The fonts are Source Sans Pro and Source Code Pro. It is made possible through sponsorships from products and services we like.