Today we will talk about web responsive images, a very popular topic and quite problematic.
If you search this topic you will find countless articles with all sorts of explanations, however I will won’t repeat those and teach you differently.
Load images correctly, increase your SEO ranking and offer a better user experience for your website.
Responsive images will (should) automatically adjust to fit the size of the screen. But… is that the correct way of doing it? Well, yes and no. If you google about this or look at modern frameworks like Bootstrap, you will notice that their definition of “responsive images” is a simple CSS similar to:
1max-width: 100%; 2height: auto;
Whilst this “works”, it’s not entirely correct. There are several reasons why, but the most important one is image size. I’m not talking about the “width/height” of the image, I am talking about the actual image size in kilobytes/megabytes.
Most websites (like 80% of websites I’ve seen in all these years), use incredibly large images on their websites and simply “scale” them up and down. Such an image is usually from 1000px to even 4000px and I even saw 8000px!!! (how crazy is that).
These images tend to be very big in size, from 1 MB to 10 and even 20 MB in size. I very rarely seen people compress their images when they are exporting them. With that being said, just imagine when you have an image heavy website composed of 5,10, 20 or more images and a user visits your website on Mobile. Even on 5G, that’s a lot of data to download just for the images, not mentioning the rest.
Browsers come into help with the support of image source set (
srcset). With this feature we can effectively have several versions of the image in different sizes and the browser will pick the right one based on the screen size. Now that’s responsive!
However, most people cannot deal with image source sets due to several reasons, from “I have no idea” to “I don’t understand” and many other.
As technology has evolved, we can now use online tools and API’s to create these source sets automatically for us. But hold your horses, creating these automatically does not mean you can simply copy paste the result and expect it to work properly.
From all my work and tests ever done, there is no “one fits all” solution and you are always required to do some extra work.
This is the first and most important thing you must understand. You can use the traditional
<img /> or the modern
Each has it’s own pitfall, but from my own experience
<picture> always wins. This tag is widely supported by browsers so that shouldn’t be an issue.
There is no automatic way to generate the correct sizes (from what I know) for a dynamic website. Take for example the well known WordPress, it will generat herratic and wrong sizes depending on what image you upload and where you place it.
Using img tags
tags are on the majority of websites out there; for responsive images the
<img /> tags are combined with
srcset attribute, but I can tell you with confidence that none of them are functioning correctly.
One of the issues is that the
<img /> tag does not function correctly on some browsers, for instance Chrome. I actually have an issue opened on stackoverflow.com
regarding this with no explanation why.
Another issue is that getting the
sizes attribute right is a pain. There are lots and lots of articles with very blunt and incomplete explanations which frankly I found very frustrating.
With that being said, I will not discuss using
<img /> for responsive images because it’s pointless (in my opinion).
Using picture tags
The picture tags are the best from my opinion, it allows us to manipulate and instruct the browser to load the image we want to.
It also supports a lot of other features like specifying art direction, alternative image formats and more. With this nice set of abilities we can achieve our goal.
No problem though, it was time for this browser to die this year .
As mentioned above, we can use many tools online to resize and generate the correct images and source code for us with a few clicks only.
I recommend you to use this one: https://responsivebreakpoints.com/ as a starting point. The tool will resize your images and generate the breakpoints to have responsive images.
For example the dog picture on their site, will have several different images resized and their respective HTML code:
1<picture> 2 <source 3 media="(max-width: 767px)" 4 sizes="(max-width: 1534px) 100vw, 1534px" 5 srcset=" 6 dog_ar_1_1,c_fill,g_auto__c_scale,w_200.jpg 200w, 7 dog_ar_1_1,c_fill,g_auto__c_scale,w_493.jpg 493w, 8 dog_ar_1_1,c_fill,g_auto__c_scale,w_707.jpg 707w, 9 dog_ar_1_1,c_fill,g_auto__c_scale,w_877.jpg 877w, 10 dog_ar_1_1,c_fill,g_auto__c_scale,w_1032.jpg 1032w, 11 dog_ar_1_1,c_fill,g_auto__c_scale,w_1108.jpg 1108w, 12 dog_ar_1_1,c_fill,g_auto__c_scale,w_1259.jpg 1259w, 13 dog_ar_1_1,c_fill,g_auto__c_scale,w_1353.jpg 1353w, 14 dog_ar_1_1,c_fill,g_auto__c_scale,w_1468.jpg 1468w, 15 dog_ar_1_1,c_fill,g_auto__c_scale,w_1534.jpg 1534w"> 16 <source 17 media="(min-width: 768px) and (max-width: 991px)" 18 sizes="(max-width: 1983px) 70vw, 1388px" 19 srcset=" 20 dog_ar_4_3,c_fill,g_auto__c_scale,w_538.jpg 538w, 21 dog_ar_4_3,c_fill,g_auto__c_scale,w_793.jpg 793w, 22 dog_ar_4_3,c_fill,g_auto__c_scale,w_1004.jpg 1004w, 23 dog_ar_4_3,c_fill,g_auto__c_scale,w_1198.jpg 1198w, 24 dog_ar_4_3,c_fill,g_auto__c_scale,w_1238.jpg 1238w, 25 dog_ar_4_3,c_fill,g_auto__c_scale,w_1384.jpg 1384w, 26 dog_ar_4_3,c_fill,g_auto__c_scale,w_1388.jpg 1388w"> 27 <source 28 media="(min-width: 992px) and (max-width: 1199px)" 29 sizes="(max-width: 2400px) 60vw, 1440px" 30 srcset=" 31 dog_ar_16_9,c_fill,g_auto__c_scale,w_596.jpg 596w, 32 dog_ar_16_9,c_fill,g_auto__c_scale,w_877.jpg 877w, 33 dog_ar_16_9,c_fill,g_auto__c_scale,w_1086.jpg 1086w, 34 dog_ar_16_9,c_fill,g_auto__c_scale,w_1314.jpg 1314w, 35 dog_ar_16_9,c_fill,g_auto__c_scale,w_1440.jpg 1440w"> 36 <img 37 sizes="(max-width: 7000px) 40vw, 2800px" 38 srcset=" 39 dog_c_scale,w_480.jpg 480w, 40 dog_c_scale,w_713.jpg 713w, 41 dog_c_scale,w_1036.jpg 1036w, 42 dog_c_scale,w_1180.jpg 1180w, 43 dog_c_scale,w_1313.jpg 1313w, 44 dog_c_scale,w_1433.jpg 1433w, 45 dog_c_scale,w_1606.jpg 1606w, 46 dog_c_scale,w_1748.jpg 1748w, 47 dog_c_scale,w_1884.jpg 1884w, 48 dog_c_scale,w_2015.jpg 2015w, 49 dog_c_scale,w_2133.jpg 2133w, 50 dog_c_scale,w_2260.jpg 2260w, 51 dog_c_scale,w_2377.jpg 2377w, 52 dog_c_scale,w_2345.jpg 2345w, 53 dog_c_scale,w_1871.jpg 1871w, 54 dog_c_scale,w_2800.jpg 2800w" 55 src="dog_c_scale,w_2800.jpg" 56 alt=""> 57</picture>
Notice how many screen dimensions it coveres for us, cool right? But is it good enough to copy paste it onto your site? NO.
The biggest problem with these image source sets is the
media attributes. It’s quite complicated to understand and even more complicated to make it work right.
With that being said, what you need to do is make the code shorter and more understandable. On my website (the one you are reading on), I have used the general responsive breakpoints provided by Bootstrap and create my own sets.
The best (and frankly only solution) is to create the image tags yourself.
This works nicely in your favour when you are developing a bespoke website from scratch, but when you have something like WordPress in place that’s another story and there will be another article regarding that.
As a starting point, I needed a clear and easy way to understand device breakpoints; so I used the ones provided from Bootstrap which are extremely reliable:
|X-Small||Small devices (portrait phones, less than 576px)||<576px|
|Small||Small devices (landscape phones, 576px and up)||≥576px|
|Medium||Medium devices (tablets, 768px and up)||≥768px|
|Large||Large devices (desktops, 992px and up)||≥992px|
|Extra large||Large devices (large desktops, 1200px and up)||≥1200px|
|Extra extra large||Large devices (larger desktops, 1400px and up)||≥1400px|
With the above I have created my “own” image source sets that loads the appropriate image as per the above device sizes:
1<picture> 2 <source srcset="" media="(min-width: 1400px)"> 3 <source srcset="" media="(min-width: 1200px)"> 4 <source srcset="" media="(min-width: 992px)"> 5 <source srcset="" media="(min-width: 768px)"> 6 <source srcset="" media="(min-width: 576px)"> 7 <source srcset="" media="(min-width: 320px)"> 8 <img src="" width="" height="" class="" alt="" > 9</picture>
This gives me a clear view and understanding of what should happen and how. In other words, I know what image should load on each device and it will do so.
Whilst this seems ready to use, it’s not quite ready just yet. Loading these images on a specific device is not good enough because the image might be still too large.
- On a large device (large desktops, 1200px and up) your container where you embed the image set is a fixed size of 800px
- The browser will look at your viewport which is 1920px for example, it will load the 1400px sized image (when in fact you would need the 768px image size…)
- On any device, your container where you embed the image set is a fixed size of 400px (this can be a card for example or a simple box)
- The browser will look at your viewport which is 1920px for example, it will load the 1400px sized image (when in fact you would need the 320px image size…)
With that being said, you are loading the wrong image, this costs you and your user. First you loose speed (which affects your SEO ranking by the way) and then your user waits forever for the image to load if he’s on a mobile or slow bandwidth.
The proper solution is to investigate your container where you embed the image and determine the right size for it.
You can do this very easily by inspecting the page and emulating different devices, usually containers stay more or less the same.
So for the above Example 1, I have amended my code as following:
1<picture> 2 <source srcset="" media="(min-width: 1200px), (min-width: 1400px), (min-width: 2500px)"> 3 <source srcset="" media="(min-width: 992px)"> 4 <source srcset="" media="(min-width: 768px)"> 5 <source srcset="" media="(min-width: 576px)"> 6 <source srcset="" media="(min-width: 320px)"> 7 <img src="" width="" height="" class="" alt=""> 8</picture>
What does this mean? It’s pretty self explanatory but I will explain anyway:
- On a device of minimum width 320px, load the 320px image
- On a device of minimum width 576px, load the 576px image
- On a device of minimum width 768px, load the 768px image
- On a device of minimum width 992px, load the 992px image
- On a device of minimum width 1200px OR 1400px OR 2500px load the 1200px image
The last line ensures that the browser does not load a bigger image size when the container size is only 800px (or 1200px in my case when you click expand article)
I find the above to be near perfect in terms of loading the right image size. Even Google Pagespeed likes it and does not generate any warnings since we are loading the right image size.
I am pretty sure after reading the above you have a general idea how to test if your images are loading correctly, however I will still explain.
The testing process can be daunting if you have many images, but it’s well worth the effort.
What you need to do is simple, it just takes some time:
- Open your desired browser and load your page
- Open the developer tools and go to the Network tab and select only “Images” filter
- Refresh your page across several devices (mobile, tablets, etc.) and see which images load
That’s it really, nothing fancy.
- If you have many images (more than a header), use the
loading=lazyattribute. You can read more about it here .
- If you cannot export your images/resize them yourself, you can use online service to do so. They will also offer CDN which will load your images crazy fast. I recommend you to use Cloudflare Images .
- Name your images right, this is very important. If you do not name your images right (like, image-small.jpg or image-320.jpg), then you cannot figure out easily which image is loading when you are testing.
Well that’s it, I hope this article has helped you.