Let’s face it. No developer is perfect. Sometimes, I make some pretty dumb mistakes. But fortunately, dumb mistakes make for great blog content (provided that they aren’t too embarrassing to admit to). So, if you’re in a situation where your responsive images do not seem to be working, even after you’ve triple-checked that your markup is correct, take a deep breath and keep reading.
Help! My Responsive Images Aren’t Working!
Responsive images aren’t always 100% intuitive, especially when you’re somewhat new to the concept, but I recently ran into an issue which left me banging my head against the wall for several minutes… and it involved what seemed like the simplest use case of all time.
Let me explain. I have a large, featured image which spans the full width of a page, and I’d like to be able to serve smaller screen (e.g. mobile users) a smaller version of the image (to keep the filesize down and be nice to people on cellular data plans). That’s all I mean by “responsive images.” Sounds easy, right?
It is! All you need to do is to specify multiple versions of the image using the srcset attribute. My full-size image is 1320 pixels wide, while my smaller version (for narrow screens) is a mere 660 pixels wide (which is still large enough to look crisp on, say, a retina iPhone).
I modified the HTML markup slightly for the purpose of this post, but the code is really as simple as this:
<img sizes="100vw" srcset="/library/images/top-feature/feature1-small.jpg 660w, /library/images/top-feature/feature1-large.jpg 1320w" alt="Featured Image" src="https://e4rpna2pel-flywheel.netdna-ssl.com/library/images/top-feature/feature1-large.jpg">
Browser Displaying the Wrong Size?
There aren’t a lot of things you can mess up in the code above. Except… when I tried it out in the browser, the large image seemed to be displaying no matter my viewport width (just using Chrome on a desktop, with the browser window resized to be only 400 pixels wide). Worse yet, I checked the “Network” tab the browser’s developer tools, and found that both the small version and the large version of the image appeared to be downloading…
Except that they weren’t actually downloading. Here’s the thing to keep in mind: the srcset attribute does not guarantee that a specific version of an image will be displayed at a specific size; instead, it gives the browser some helpful hints and lets the browser decide what’s best to show. In this case, the “large” version of the image in question was already in my browser cache; there was no need to go out and download it again. Since I already had a perfectly suitable image handy, Chrome decided to use it (the large version, rather than the smaller version) on the page, because… well, why the heck not? If the browser can render a higher-resolution image without wasting any bandwidth, it makes sense to just give me the cached (larger) image.
Solution: Clear Your Browser Cache
All it took to resolve my “problem” (which turned out not to really be a problem at all) was to simply clear my browser cache. After that, I received the smaller image within my narrow viewport as expected. Whew. Responsive image success.
As a closing note, this is a great demonstration of how the <picture> element works compared to simply using the srcset and sizes attributes on a regular <img> element. If you need to be completely sure that the user sees a certain image at a certain size (particularly if the image being used at one size is altogether different than an image at another size), use <picture>. It’s best for these situations where the art differs completely from one size to the next.
Otherwise, if you’re just swapping out different resolutions/sizes of the same image, use srcset and sizes. These attributes have better browser support than <picture>, and you probably don’t need to use a polyfill (since they degrade gracefully, falling back on the regular old src attribute on unsupported browsers). Just remember that your suggested responsive image sources specified by srcset won’t necessarily be exactly what you specify, and if you just can’t seem to figure out why you’re getting the wrong image… well, just try clearing your cache.