All is well defined in your image srcset attribute but still loads the wrong image. Let's examine the issue.
Your code for the image looks correct. Everything is defined in the
sizes attributes, but the browser downloads a completely different image than the one you expect. Let’s check why this is happening.
How does the browser determine which image should be used under some set of media conditions?
Let’s examine following example:
<img alt="" src="/images/large.jpg" srcset="/images/small.jpg 576w, /images/medium.jpg 992w, /images/large.jpg 1920w" sizes="(min-width: 575.98px) 100vw, (min-width: 991.98px) 100vw, (min-width: 1919.98px) 100vw, 100vw" />
The browser then will:
- Determine device width.
- Determine which of the media conditions in the
sizeslist is the first to be true.
- Examine the slot size given to the media query.
- Load the image referenced in the
srcsetlist that is the same size as the slot or the first image that is larger than the given slot size if there isn’t one.
srcset specifies the collection of images from which the browser can select, as well as the size of each image. A comma separates each set of image information from the preceding one. The syntax then is: [
intrinsic width in pixels]. Example:
Note that there is
w unit, not
px. The image intrinsic size is the real image size. You can check that for example in Brave browser by opening developer tools, going to the Elements section, finding the image, and moving the mouse over the image URL. Example:
When specific media circumstances are met, the attribute
sizes sets up a set of media conditions (e.g., screen widths) and determines what image size to use.
The user visits your site with the iPhone 8 Plus. Which image will be used?
iPhone 8 Plus viewport size is defined as
414px width and
736px height, but the image that is downloaded isn’t what you’d expect. See the example from Chrome browser version 110.0.5481.100 (Official Build) (x86_64):
So, seems like
1px doesn’t mean always
1px. That’s because there are physical pixels and device-independent pixels. So, to get a real viewport size we need to also know the resolution scale factor for the specified device (the ratio between physical pixels and logical CSS pixels).
We need to determine the device pixel ratio. For that purpose use window.devicePixelRatio. Example from Chrome:
So, we’ve got here scale factor
3. Which is called
UIKit Scale. However, the
Native Scale factor is
The real viewport size for iPhone 8 Plus is
1080 x 1920 and it comes from following calculation: 414px x 2,608 = 1080px and 736px x 2,608 = 1920px.
Is there a better way of testing responsive images?
Safari on MacOS and Firefox can be used for responsive image testing. See the example from Safari version 16.3 (186188.8.131.52.6):
You can test how it works in various scenarios using the following Responsive Images example.