I'm trying to optimize a page which consists of a grid of images with breakpoints that makes it use 1, 2, 3 or 4 columns.
The html looks like this:
<img
srcset="
image-300x200.jpg 300w,
image-original.jpg 600w"
sizes="
(min-width: 1px) calc( 100vw * (0.94 * 1.000) * 1.00 ),
(min-width: 480px) calc( 100vw * (0.94 * 0.905) * 0.50 ),
(min-width: 768px) calc( 100vw * (0.94 * 0.850) * 0.33 ),
(min-width: 981px) calc( 100vw * (0.94 * 0.835) * 0.25 ),
280px"
alt="E-Books customer service for Dutch Libraries"
width="400" height="284">
The calc() functions may look a bit complicated but I've tested them with various viewport widths and then verified the size of the image in the browser and the math checks out.
For completeness, here's what it does:
[viewport width] - [94% container width] - [column gutters] / [nr of columns]
But whatever I try, Chrome (almost, yay for consistency) always selects the big image even when the size of the img on screen is well below 300px. I checked this in the developer tools > inspector > properties > img > currentsrc as pointed out in this answer
Can anyone help me?
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.
You can use sizes to make srcset work even better. Without it, the browser uses the full width of the viewport when choosing an image from a srcset .
The srcset attribute on an <img> tag specifies multiple image resources (URLs) for the img element. Together with the sizes attribute they create responsive images that adjust according to browser conditions.
srcset - To define multiple image sources of different widths and let the browser pick the most appropriate candidate during HTML parsing. sizes - To define the size of the image element. It could be a fixed size like 225px or relative to the viewport.
I think I figured it out. it seems that the media queries don't work as I expected.
For example, with these rules:
sizes="
(min-width: 1px) ...
(min-width: 480px) ...
(min-width: 768px) ...
"
one would assume that
This is not how it works, at least not in practice. I think that the browser just looks for a rule that evaluates to true and calls it a day.
So it just goes:
When I looked at my rules and the result with this logic in mind, it suddenly made sense that the browser insisted on using the biggest image because the calc() function I use for the first line is:
calc( 100vw * (0.94 * 1.0) * 1.0 )
- which is a complicated way of writing windowWidth * 0.94
.
In other words, the browser assumes that the image is always 94% of the entire width of the window and doesn't apply any of the other calculations that take the breakpoints into account.
Anyway, changing the above rules to this:
sizes="
(min-width: 1px) and (max-width: 479px) ...
(min-width: 480px) and (max-width: 767px) ...
(min-width: 768px) and (max-width: 980px) ...
"
makes sure that the rule only applies up to a certain point. Every time the next line evaluates as true, the other lines don't.
So this is what I went with in the end:
<img src="image-fallback.jpg"
srcset="
image-300x200.jpg 300w,
image-480x320.jpg 480w,
image-600x400.jpg 600w,
image-960x640.jpg 960w,
image-1200x800.jpg 1200w"
sizes="
(min-width: 1px) and (max-width: 479px) calc( 100vw * (0.94 * 1.000) * 1.00 ),
(min-width: 480px) and (max-width: 767px) calc( 100vw * (0.94 * 0.905) * 0.50 ),
(min-width: 768px) and (max-width: 980px) calc( 100vw * (0.94 * 0.850) * 0.33 ),
(min-width: 981px) and (max-width: 1088px) calc( 100vw * (0.94 * 0.835) * 0.25 ),
(min-width: 1089px) calc( 1089px * (0.94 * 0.835) * 0.25 ),
280px"
/>
And here's a working example of the above: Image srcset example (working)
Note: once the browser has loaded a larger image, it's reluctant to load smaller ones. That's what the 'force refresh' button is for.
Note #2: For debugging I added more source images compared to my original question. I thought it would be easier to keep it simple with two sizes but I think I would have never figured this out if I hadn't added a bunch. When I only had 2 images, I thought it always chose the biggest. That isn't true, it just never chose the image I expected ;)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With