lozad.js icon indicating copy to clipboard operation
lozad.js copied to clipboard

Picture Element Lazy Loading

Open Jab2870 opened this issue 6 years ago • 11 comments

Firstly, thanks fo creating this amazing tool. I use it on almost every website I build. I would, however, like to open a discussion about the way that picture elements are lazy-loaded.

Why not just put the class lozad on the picture element and add then, when it enters the viewport, change all data-srcset attributes to srcset attributes on the source elements and on the img element, do the same but also change data-src elements to src elements.

The markup would then just become

<picture class="lozad">
    <source data-srcset="image.png">
    <img data-src="image2.png">
</picture>

Adding the data-iesrc attributes to the picture elements etc just seems confusing to me and I'm not sure what benefit it brings.

I would be very happy to submit a PR if this is something you are interested in?

Jab2870 avatar Nov 10 '18 09:11 Jab2870

I agree with you that this implementation is very confusing.

Other lazyloading plugins solved this in such better ways. Would be very satisfying to solve this.

lchinke avatar Nov 27 '18 15:11 lchinke

Agreed. Especially the fact that you can't add <img>, making it unable to have css classes. And also it loses backward compatibility with older browsers because the <img> added by the library doesnt have src attribute.

@ApoorvSaxena

netok421 avatar Dec 30 '18 18:12 netok421

I also agree with @Jab2870's suggested solution. I ran into the same problems when I wanted to assign a class to the img tag which currently isn't possible

staffe avatar Feb 25 '19 11:02 staffe

As someone who is working with picture tags all the time, this implementation feels much better than the current one. Already using the patch on my end. Thumbs up @Jab2870.

bitbruder avatar Feb 26 '19 18:02 bitbruder

I'm having an issue where it's saying it's loading but is in fact only entering an empty tag. But that fact that you can't have CSS on the image tag is enough of a reason for me to switch.

TomS- avatar May 14 '19 10:05 TomS-

I like the implementation proposed by @Jab2870 as well, having the ability to attach to the img element for styling is very important.

aeu avatar May 01 '20 03:05 aeu

Correct me if I'm wrong, but here's an idea:

<picture>
  <source srcset="/image-1280.jpg" media="(min-width: 1280px)" />
  <img data-src="/image-fallback.jpg" class="lozad" />
</picture>

Output:

<picture>
  <source srcset="/image-1280.jpg" media="(min-width: 1280px)" />
  <img
    data-src="/image-fallback.jpg"
    class="lozad"
    src="/image-fallback.jpg"
    data-loaded="true"
  />
</picture>

Don't add a lozad class directly to the <picture> tag, but to the <img> tag. This way you can add custom styles (such as aspect-ratio or additional classes) to the <picture> and <img> tags. You also avoid the confusing data-iesrc attribute.

ivodolenc avatar Dec 29 '20 20:12 ivodolenc

As someone who is working with picture tags all the time, this implementation feels much better than the current one. Already using the patch on my end. Thumbs up @Jab2870.

Hello mate, you wouldn't happen to have that modified file would you? I don't know how to patch lozad.js with this diff file.

teebling avatar Feb 23 '21 23:02 teebling

Hey @teebling, just use patch-package - its super easy and well documented. By the way: you can get patch files from any pull request by just adding ".patch" to the end of any pull request URL.

See this PR im using? https://github.com/ApoorvSaxena/lozad.js/pull/145

Just add ".patch" to the end of the URL and see what happens. :-)

bitbruder avatar Mar 02 '21 07:03 bitbruder

I'd rather avoid maintaining my own patched version of any 3rd party software. As a workaround, I've used this:

<picture class="picture-lozad">
  <source data-srcset="image.png">
  <img class="whichever-classes-i-need" data-src="image2.png" alt="whatever-alt-i-need">
</picture>

<script>
const picture_observer = lozad('.picture-lozad', {
  load: function(el) {
    $(el).find('source').each(function(){$(this).attr('srcset', $(this).attr('data-srcset'))})
    $(el).find('img').each(function(){$(this).attr('src', $(this).attr('data-src'))})
  }
});
picture_observer.observe();
</script>

This has the benefit that you get to use any classes you might need for layout at the <img> and also to place the 'alt' attribute right where it belongs. I use 'data-srcset' instead of just 'srcset' in the <source> elements because modern browsers will fetch their preferred image from the 'srcset' even if the <img> itself has no 'src', thus bypassing the whole lazy image loading behavior that was intended in the first place.

jsandeo avatar Apr 08 '22 07:04 jsandeo

I'd rather avoid maintaining my own patched version of any 3rd party software. As a workaround, I've used this:

<picture class="picture-lozad">
  <source data-srcset="image.png">
  <img class="whichever-classes-i-need" data-src="image2.png" alt="whatever-alt-i-need">
</picture>

<script>
const picture_observer = lozad('.picture-lozad', {
  load: function(el) {
    $(el).find('source').each(function(){$(this).attr('srcset', $(this).attr('data-srcset'))})
    $(el).find('img').each(function(){$(this).attr('src', $(this).attr('data-src'))})
  }
});
picture_observer.observe();
</script>

This has the benefit that you get to use any classes you might need for layout at the <img> and also to place the 'alt' attribute right where it belongs. I use 'data-srcset' insted of just 'srcset' in the <source> elements because modern browsers will fetch their preferred image from the 'srcset' even if the <img> itself has no 'src', thus bypassing the whole lazy image loading behavior that was intended in the first place.

Nice solution!

jcsuzanne avatar Sep 01 '22 11:09 jcsuzanne