OwlCarousel2 / OwlCarousel2

DEPRECATED jQuery Responsive Carousel.
http://owlcarousel2.github.io/OwlCarousel2/
Other
7.92k stars 2.27k forks source link

Lazy loading not working as expected with srcset and wp_get_attachment_image in Wordpress theme #2384

Open ligne13 opened 6 years ago

ligne13 commented 6 years ago

Hi, I'm trying to use lazyload in image sliders in a Wordpress theme. The <img> tag is the output of the Wordpress function wp_get_attachment_image. I search and replace for src and srcset attributes to replace them with data-src dans data-srcset attributes before outputting the HTML :

function slider_lazyload($string) {
    $string = str_replace("src=", "data-src=", $string);
    $string = str_replace("srcset=", "data-srcset=", $string);
    return $string;
}

The HTML looks like this (only 3 slides for this example to make it shorter) :

<div class="owl-carousel">
    <div style="width: 265px;">
        <img width="265" height="265" data-src="/wp-content/uploads/2018/06/img1-265x265.jpg" class="owl-lazy" alt="" data-srcset="/wp-content/uploads/2018/06/img1-265x265.jpg 265w, /wp-content/uploads/2018/06/img1-150x150.jpg 150w, /wp-content/uploads/2018/06/img1-560x560.jpg 560w, /wp-content/uploads/2018/06/img1-300x300.jpg 300w, /wp-content/uploads/2018/06/img1-100x100.jpg 100w" sizes="(max-width: 265px) 100vw, 265px" />
    </div>
    <div style="width: 265px;">
        <img width="265" height="265" data-src="/wp-content/uploads/2018/06/img2-265x265.jpg" class="owl-lazy" alt="" data-srcset="/wp-content/uploads/2018/06/img2-265x265.jpg 265w, /wp-content/uploads/2018/06/img2-150x150.jpg 150w, /wp-content/uploads/2018/06/img2-560x560.jpg 560w, /wp-content/uploads/2018/06/img2-300x300.jpg 300w, /wp-content/uploads/2018/06/img2-100x100.jpg 100w" sizes="(max-width: 265px) 100vw, 265px" />
    </div>
    <div style="width: 265px;">
        <img width="265" height="265" data-src="/wp-content/uploads/2018/06/img3-265x265.jpg" class="owl-lazy" alt="" data-srcset="/wp-content/uploads/2018/06/img3-265x265.jpg 265w, /wp-content/uploads/2018/06/img3-150x150.jpg 150w, /wp-content/uploads/2018/06/img3-560x560.jpg 560w, /wp-content/uploads/2018/06/img3-300x300.jpg 300w, /wp-content/uploads/2018/06/img3-100x100.jpg 100w" sizes="(max-width: 265px) 100vw, 265px" />
    </div>
</div>

I added the class owl-lazy in each <img> tag.

The generated HTML is (only one <img> tag is pasted below):

<div class="owl-carousel">
    <div style="width: 265px;">
        <img width="265" height="265" data-src="/wp-content/uploads/2018/06/img1-265x265.jpg" class="owl-lazy" alt="" data-srcset="/wp-content/uploads/2018/06/img1-265x265.jpg 265w, /wp-content/uploads/2018/06/img1-150x150.jpg 150w, /wp-content/uploads/2018/06/img1-560x560.jpg 560w, /wp-content/uploads/2018/06/img1-300x300.jpg 300w, /wp-content/uploads/2018/06/img1-100x100.jpg 100w" sizes="(max-width: 265px) 100vw, 265px" src="http://hotelibanais.test/wp-content/uploads/2018/06/img1-265x265.jpg" style="opacity: 1;">
    </div>
</div>

And my JS code to initialize the slider :

$('.owl-carousel').owlCarousel({
        autoWidth: true,
        center: true,
        loop: true,
        margin: 20,
        lazyLoad: true,
});

My issue is that the srcset is not generated from the data-srcset attribute, as you can see in the generated HTML. Only the src attribute is generated from the data-src. The official demo shows it is possible with the '' tag. Isn't it possible with data-srcset on the <img> tag ?

tmtung144 commented 5 years ago

add class "owl-lazy" in tag <img>

ligne13 commented 5 years ago

Hi @tmtung144,

the class is already there !

cleitontortato commented 3 years ago

I'm here because the same issue, but I look on OwlCarousel code and found that's prepared just to work with picture and source tags, see html session on this page: https://owlcarousel2.github.io/OwlCarousel2/demos/lazyLoad.html

Example:

<picture>
      <source class="owl-lazy" media="(min-width: 650px)" data-srcset="https://placehold.it/350x250&text=3-large">
      <source class="owl-lazy" media="(min-width: 350px)" data-srcset="https://placehold.it/350x250&text=3-medium">
      <img class="owl-lazy" data-src="https://placehold.it/350x250&text=3-fallback" alt="">
  </picture>

I change my code to this format and work for me

rentptr commented 2 years ago

I was able to get it to work by adding wrapping the initiating code into a pseudo .delay. My issue was the carousel was set to display:none on page load to eliminate the large content-shift. This led to the lazy loader not being able to capture the correct <img> src so it would only show a base64 .gif

<img src="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==" alt="Pickup Truck Rental">

Example:

jQuery(function(t){
    t(".owl-carousel").fadeTo(100, 0);
    function owl(){
        t(".owl-carousel").fadeTo(1000,1);
        t('.owl-carousel').owlCarousel({
            lazyLoad: true,
            items: 1,
            loop: true,
            nav: true,
            dots: false,
                    thumbs: true,
                    thumbImage: true,
                    thumbContainerClass: "owl-thumb",
                    thumbItemClass: "owl-thumb-item",
                    moveThumbsInside: true,
            onInitialized: function() {
                t("a.has-gallery").featherlightGallery({
                    galleryFadeIn: 300,
                    openSpeed: 300
                })
            }
        })

    };

The 5th line is where the carousel initializes.

t('.owl-carousel').owlCarousel({

The 2nd line loads the carousel stage but quickly changes the opacity to 0..

t(".owl-carousel").fadeTo(100, 0);
function owl(){
    t(".owl-carousel").fadeTo(1000,1);

On the page has loaded a function is ran to set the opacity to 1. This is shown on line 4.

t(".owl-carousel").fadeTo(1000,1);

Thus achieving the lazy load feature with OwlCarousel2

baddon250 commented 7 months ago

I tried all of the above solutions for this problem and none of them worked. After about 16 hours of failing, it was very clear that owl-carousel does not work well with data-srcset, so I blazed a trail in software and made it happen. This works well because it lazy loads the most optimal image per screen size in the lazy that we all love. Here is the script required, as well as the html markup I used. It works figuring out the client screen size and setting the data-src to the desired resolution found in the data-srcset, and it initiates when the owl-carousel gets initialized so it always runs at the right time. Make sure you include the updateOptimalDataSrc to the onInitialized action for owl-carousel

`$(".product-gallery-left .owl-carousel").owlCarousel({ autoplay: true, autoplayHoverPause: true, autoplaySpeed: 3000, animateOut: 'animateOut', animateIn: 'animateIn', lazyLoad: true, // Enable lazy loading loop:true, dots: false, margin: 5, items: 1, //nav: true, //navText: ["", ""], // This callback ensures that the number of items adapts based on the actual number of slides onInitialized: updateOptimalDataSrc });

function updateOptimalDataSrc() {
    // Select all images with a 'data-srcset' attribute
    $('img[data-srcset]').each(function() {
        var $img = $(this);
        var viewportWidth = $(window).width();
        var srcset = $img.attr('data-srcset').split(',').map(function(src) {
            var parts = src.trim().split(' ');
            return {
                url: parts[0],
                width: parseInt(parts[1], 10)
            };
        });

        // Sort srcset entries by width in ascending order
        srcset.sort(function(a, b) {
            return a.width - b.width;
        });

        // Find the most suitable image
        var optimalImage = srcset.find(function(entry) {
            return entry.width >= viewportWidth;
        }) || srcset[srcset.length - 1]; // Fallback to the largest image if none match

        // Set the optimal image URL as the value of the 'data-src' attribute
        $img.attr('data-src', optimalImage.url);
    });
}`

<img class="gallery-img owl-lazy" data-src="https://biltpros.com/wp-content/uploads/bp_galleries/product_category/kitchen/image_65f3536f083c75.51718295-medium-large.png" data-srcset="https://biltpros.com/wp-content/uploads/bp_galleries/product_category/kitchen/image_65f3536f083c75.51718295-medium.png 300w, https://biltpros.com/wp-content/uploads/bp_galleries/product_category/kitchen/image_65f3536f083c75.51718295-medium-large.png 600w, https://biltpros.com/wp-content/uploads/bp_galleries/product_category/kitchen/image_65f3536f083c75.51718295-medium.png 800w, https://biltpros.com/wp-content/uploads/bp_galleries/product_category/kitchen/image_65f3536f083c75.51718295-medium-large.png 1000w" data-sizes="(min-width: 300px) 600px, (min-width: 600px) 800px, (min-width: 800px) 1000px, (min-width: 1000px) 100vw" alt="Responsive Image" src="https://biltpros.com/wp-content/uploads/bp_galleries/product_category/kitchen/image_65f3536f083c75.51718295-medium-large.png" style="opacity: 1;">