So, you took the trouble to set up all the different image sizes with srcset. You think that a particular image should be used. But, the browser is using a bigger image. Or maybe the wrong image. srcset is not working how you thought it would. This guide will help you fix all that.
How Does The Browser Figure Out Which Image Is To Be Used?
Let us consider the below case…
You can see the live version of the above here.
If you see the code, srcset is set up in the following way…
(By the way, if you don’t quite understand what is going on with the above code, I recommend you start with this article: How Do I Optimize An Image For Web Without Losing Quality?)
A User Comes To Your Page With A iPhone 12 Pro. Which image is used?
If we try to simulate this with Chrome Dev tools, we see…
There are a few problems here:
- According to the Chrome: the size of the iPhone 12 Pro is ONLY 390px by 844px. Wait a second! That cannot be right. That is a very low resolution for an iPhone 12 Pro!! According to the Apple website, here are the specifications.
- On this 390px screen, Chrome has loaded up a 1200px image. That seems wrong. The image being used by Chrome seems way too big.
Below is a screenshot from the Apple website…
So, Chrome is saying the smaller dimension is 390px. But, Apple says it’s, 1170px.
Let us understand why this difference exists from Steve Jobs himself. He has explained it so well in this video. So, do look at it.
As you can see, 1px may or may not mean 1px. It may be many more!
But, do not be under the impression that only Apple devices do this. All modern devices do this! Apple just came up with a catchy name for it: Retina Displays.
It turns out, there are more pixels than 390 in reality! Chrome is accounting for all of them.
You can ask Chrome to tell you about how many “real/physical” pixels are packed into one of these “virtual” pixels. To do that, you just run this line of Javascript:
So, this means that when Chrome says that the iPhone 12 has 390 virtual pixels, and a “devicePixelRatio” of 3, its real width is:
390px x 3 = 1170px
Hey! That exactly matches the 1170px that Apple is claiming!
So, if that’s the case, then what image should Chrome be using given that the srcset HTML code is..
Chrome is using the 1200px image because it’s just slightly larger than the size that’s needed: 1170px. Good job Chrome!
Turns out it’s not the wrong image after all!
Some Notes On Execution
- When deciding the sizes in which I should generate my images, I have used the list from Next.js which can be found here.
- Manually making images is going to be a HUGE PAIN! So, I am hoping you are using an Image CDN with WebP support!
TLDR / Summary
If you find yourself confused about why srcset is not working as expected. And why the browser is using the wrong image, it’s probably because of “devicePixelRatio”. Once you factor that into your estimations, things will start to look right.