HTML 5 picture element, srcset and sizes attributes
What's this all about?
In recent years there has been a steady increase in the number of responsive websites. RWD is a great concept that helps designers create user-friendly and consistent websites that work well across the full range of devices. RWD can also be combined with tools like device detection to fine-tune performance and help reduce page sizes for mobile devices. Historically however, images and graphics have been the Achilles heel of RWD. Images were supplied as is: without consideration of physical device size or even the bandwidth available. This caused a lot of problems for all manner of mobile devices. Amongst the largest problems was the amount of data that a mobile device had to download in order to render the page. Some lower-end devices and older devices would experience slowness and sometimes crash.
Fortunately the RWD community is opening up to the idea of different image sizes for different viewing platforms. The issue is addressed through Responsive Images, where a browser can request an image of the relevant size based on some condition (usually browser window width). In a nutshell, we have one new HTML element called <picture> and two new attributes: srcset and sizes for the existing <img> tag.
You will find working examples with explanations and code snippets below. For the purpose of this demo I have manually resized one picture to different sizes: 200px, 400px, 600px, 800px and 1000px. You can also download the original image (5Mb). This picture is my own work, and is distributed under CC BY 4.0 should you wish to use it for any purpose.
<picture> example
<picture>
<source media="(min-width: 800px)" srcset="/Portals/0/EasyGalleryImages/1/159/crabs800.jpg, /Portals/0/EasyGalleryImages/1/159/crabs800.jpg 1.5x, /Portals/0/EasyGalleryImages/1/159/crabs800.jpg 2x">
<source media="(min-width: 600px)" srcset="/Portals/0/EasyGalleryImages/1/159/crabs600.jpg, /Portals/0/EasyGalleryImages/1/159/crabs600.jpg 1.5x /Portals/0/EasyGalleryImages/1/159/crabs600jpg 2x">
<source media="(min-width: 400px)" srcset="/Portals/0/EasyGalleryImages/1/159/crabs400.jpg, /Portals/0/EasyGalleryImages/1/159/crabs400.jpg 1.5x /Portals/0/EasyGalleryImages/1/159/crabs400jpg 2x">
<img src="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg" srcset="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg 1.5x, /Portals/0/EasyGalleryImages/1/159/crabs800.jpg 2x" alt="Pair of crabs">
</picture>
The above HTML snippet declares a <picture> element. A browser will automatically choose the <source> for the image based on some condition, in this case the minimum width. The last element - <img> is used as a fall-back point in case there is a problem with all of the above conditions. At the time of writing Firefox did not support this element, so it would fall back to the <img> tag. So, if you see that crabs1000.jpg is set as picture source it means that your browser does not support the <picture> element. If the element is supported, the closest <source> condition will be selected, i.e. crabs800.jpg in full screen. Try resizing the window to see how the image requested changes to crabs600.jpg and crabs400.jpg.
<img> example
You can also integrate responsiveness directly in to the <img> element as shown below:
<img src="/Portals/0/Empty.gif"
sizes="(min-width: 1200px) 40vw, (min-width: 800px) 60vw, (min-width: 400px) 80vw, 100vw"
srcset="/Portals/0/EasyGalleryImages/1/159/crabs200.jpg 200w,
/Portals/0/EasyGalleryImages/1/159/crabs400.jpg 400w,
/Portals/0/EasyGalleryImages/1/159/crabs600.jpg 600w,
/Portals/0/EasyGalleryImages/1/159/crabs800.jpg 800w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg 1000w">
Two things happen in this example. First, based on the min-width attribute the picture will take a certain percentage of the viewport space. For example: in a range between 1200px and 800px the image should take up 60% of the viewport width. Secondly, the browser is free to choose one of the pictures specified in the srcset attribute. In this case your browser will choose a picture that is closer to the current width. For example: if current width is 800px, then the crabs800.jpg picture will be chosen. Working example:
At the time of writing the only browsers that support this feature are: Chrome and Opera. If you don't see an image directly above, it means your browser does not support srcset. Try resizing the window and check out how a different image is loaded for each 200 pixel interval. You should notice that the less space there is the more space the picture takes.
Good news, right?
Indeed. But who or what will create several versions of the existing images? It's a time consuming and costly activity.
Why? Because this small change translates in to an unquantifiable amount of man-hours of work on the global scale and therefore we can safely assume that the majority of designers will be reluctant to adopt this approach in the near future.
51Degrees approach
At 51Degrees we welcome these changes. But we also think that this technology is still very young, even by modern standards, to be deployed to production straight away. At least until all major browsers fully support all of the new features. 51Degrees provides an image optimization solution with both manual and automatic optimization options.
Automatic image optimization:
<img src="/Landscape.jpg?w=auto" style="width:100%;"/>
becomes:
<img src="/Empty.gif" data-src="/Landscape.jpg?w=auto" style="width:100%;"/>
Simple, right? And it works great with Responsive Web Design. Change the width of the image container element with media queries and the automatic image optimizer will pick the relevant picture size for you. This approach is simple and does the resizing for you. What's more - you can configure pixel size ranges, so that you can have an image for every size range.
The manual mode:
<img src=”/Landscape.jpg?w=300”/>
This is where you explicitly tell image optimizer what width or height (or both) you want. This approach also works well for frontend developers. It allows them to use JavaScript to add images in the required place based on some logic. The following code snippet demonstrates how this feature could be used. Your approach can be different:
This function adds a new image element to the page. For the sake of this example the image is added to body element.
<script type="text/javascript">
function addImage(src, width, alt) {
var img = document.createElement("img");
src = src + "?w=" + width;
img.src = src;
img.alt = alt;
document.body.appendChild(img);
}
</script>
The above script can then be invoked to add the element as follows:
<script type="text/javascript">
addImage("disk.PNG", "600", "Image of hard drive");
</script>
The above examples are created with .NET in mind, but the approach is similar on other platforms.
The combined approach
I'm sure you will like this part as it shows you how to combine Responsive Images with 51Degrees Image Optimizer! You will be able to enjoy the benefits of Responsive Images without having to worry about resizing them. This way you can leave all the repetitive and tedious tasks to the computer and concentrate on the things that matter.
I will be using the crabs1000.jpg image to demonstrate how easy it is to integrate our image optimizer with Responsive Images. The general idea is to use the manual image optimizer links in place of the original image links.
<picture> example
Let's edit the HTML snippet from the previous <picture> example by replacing all links to pictures with the link to one original picture and supply the width parameter in the form of crabs1000.jpg?w=width. Updated snippet:
<picture>
<source media="(min-width: 800px)" srcset="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=800, /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=800 1.5x, /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=800 2x">
<source media="(min-width: 600px)" srcset="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?w=600, /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?w=600 1.5x /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?w=600 2x">
<source media="(min-width: 400px)" srcset="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?w=400, /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?w=400 1.5x /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?w=400 2x">
<img src="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg" srcset="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg 1.5x, /Portals/0/EasyGalleryImages/1/159/crabs1000.jpg 2x" alt="Pair of crabs" style="width: 100%;">
</picture>
In this example you will see a picture even if your browser does not support Responsive Images yet. Try resizing your browser window to see how the image link changes with size.
<img> example
To integrate 51Degrees image optimizer with the existing <img> tags all you need to do is add the width parameter to the image URL. So, an image link crabs1000.jpg will become crabs1000.jpg?w=desired_width. Since I no longer need to do any manual resizing I can create as many resolution ranges as I want. So, our HTML from the first <img> example becomes:
<img src="/Portals/0/Empty.gif"
sizes="(min-width: 1200px) 85vw, (min-width: 800px) 90vw, (min-width: 400px) 95vw, 100vw"
srcset="/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=100 100w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=150 150w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=200 200w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=250 250w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=300 300w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=350 350w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=400 400w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=450 450w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=500 500w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=550 550w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=600 600w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=650 650w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=700 700w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=750 750w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=800 800w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=850 850w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=900 900w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=950 950w,
/Portals/0/EasyGalleryImages/1/159/crabs1000.jpg?width=1000 1000w">
And here's how this example looks:
Try resizing your browser window. Below is another example, this time without the viewport specified. Check out how the image decreases in size when you make your browser window smaller.
Easy, right? No need to manually go through all of those images and waste time on resizing. What's more, image resizing is done on-site. Unlike cloud based solutions the on-site image resizing is fast as it does not require additional external requests and DNS lookups. With an on-site solution you are in control. Additionally our solution is distributed under MPL2, which is far more flexible and permissive than GPL which is common among other vendors.
Conclusion
Responsive Images are a wonderful new technology and I have no doubt that many designers will adopt it in their work. However, Responsive Images can become an even more powerful tool when used in conjunction with the 51Degrees Image Optimizer solution. We are looking forward to this technology making its way in to all browsers. I hope that you enjoyed the article and found it useful. If you have any questions or comments please use the form below.