aFarkas/lazysizes

`sizes` can't force specific image width+height combination

strarsis opened this issue · 4 comments

Describe the bug
lazysizes + parent-fit extension can also use a combination of width (w) and height (h) descriptors in srcset, which is great!
However, the sizes attribute will get a calculated width assigned and the browser will pick the first occurrence with that width descriptor, even if there are multiple image candidates, each with different additional height (h) descriptor, that may closer or exactly match the actual image element dimensions.

  <img data-srcset="
                    https://via.placeholder.com/400x300 400w 400h,
                    https://via.placeholder.com/400x400 400w 300h
                    "
       class="lazyload"
       
       data-sizes="auto"
       data-parent-fit="cover"
       data-parent-container="self"

      style="width: 400px;height: 300px"
/>

sizes will be set to 400, as the image element is indeed 400px in width.
But it is also 300px in height. The browser will use the first occurrence, an image source of 400px x 400px instead.

To Reproduce
https://codepen.io/strarsis/pen/NWwrGRy

Steps to reproduce the behavior:
Add a lazyload+parent-fit extension using image that has multiple image source candidates, where some are equal in width but different in height. Give that image element a height that would match an image source candidate that is not the first occurrence for the image element width.

What is the expected behavior:
An image source candidate is forced that matches both, in width and height the image element.

What happened instead:
Only the width is forced, the first image source candidate is used that matches in width but can completely differ in height.

In what environment (browser/device etc.) does this bug happen/not happen:
Windows: Chrome; Firefox; Edge; Opera

Keywords help others to find this issue:
height; h; vh; combined; descriptor; candidate; sizes; w; vw; srcset; parent-fit; parent; fit

@strarsis
This is a violation of the srcset attribute. The srcset attribute only accepts the same image with different resolutions. In the future it could also be the same image with different image formats, but always the same image. Hence it has to be the same aspect ratio.

If you want different images you have to use picture with different source elements.

@aFarkas: Thanks! I will then, as you recommend, treat the different heights of the width-height combinations as art direction and use a <picture> element and some JavaScript to toggle to the <source> element closest/exact available set of heights.
Minimal example: https://codepen.io/strarsis/pen/RwjRraM

Currently that script also has to determine the element dimensions (width+height) as I don't know how to use lazysizes together with toggling <source> for height.
Would an extension for this specific use case (width-height combinations) for lazysizes make sense?
How can I write an extension for lazysizes? An API/documentation about the lazysizes extension API would be great as I want to reuse as much existing lazysizes functionality as possible. I want to modify the activation of <source> elements by lazysizes.

@strarsis
The documentation includes the hole API. Simply hook into an event to modify the DOM accordingly. You can also check the art direct plugin, which should do something similar/same? that you want:
https://github.com/aFarkas/lazysizes/blob/gh-pages/plugins/artdirect/ls.artdirect.js

@aFarkas: Yes, the artidirect- and parent-fit-plugins combined seem to have the required functionality.

Can artdirect use a specific <source> by the element height? Then the parent-fit plugin would assign the proper sizes (width) to the element and the closest/matching image source should be selected by the browser.