Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lazy loading a carousel images with LazySizes

I´m using Lazysizes to lazyload a carousel in my AngularJs app.

If I do lazysizes on images, it works, but I don´t like the effect, because the images are loaded the moment the user click on the arrow buttons to change the images, but there are some milliseconds the image is white while loading. This is the code:

<div class="carousel slide">
                            <carousel interval="-10">
                                <slide ng-repeat="i in imagesList">
                                    <img data-src="image-url.jpg" class="lazyload"  />
                                </slide>                                    
                            </carousel>
                        </div> 

However, what I would like to do is to lazyload the carousel itself. But the moment the carousel is loaded, then all images in that carousel should be loaded to avoid that ugly effect.

<div class="carousel slide lazyload">
                        <carousel interval="-10">
                            <slide ng-repeat="i in imagesList">
                                <img ng-src="image-url.jpg" />
                            </slide>                                    
                        </carousel>
                    </div>

I don´t know how to do this or if it´s possible. I think my carousel comes from bootstrap 2.3.2

like image 353
Rober Avatar asked Jun 23 '17 09:06

Rober


People also ask

Can you Lazyload background images?

vanilla-lazyload is a lightweight option for lazy-loading images, background images, videos, iframes, and scripts. It leverages Intersection Observer, supports responsive images, and enables browser-level lazy loading.

How do you use lazySizes?

Simply add the lazyload class to the img and use data-srcset on your source and the img element. automatic sizes feature: In case of lazy loading images the sizes attribute of the img / source elements can be calculated with JS. This automatic sizes feature is directly included in lazySizes.

How do I get lazy offscreen images?

With browser lazy loading, you only need to add a loading attribute with a value of lazy to the img tag in the HTML markup. Put simply, all you need to do is tell the browser which images to lazy load. No JavaScript, APIs, or calculations required.


2 Answers

Best solution is to use small, blurry fallback images for src, alongside with data-srcset. What this does is load the small thumbs on controller init and load the large ones when they come into view.
By the time they finish sliding into view, the large image is typically already loaded and displayed, replacing the blurry thumb. Even when the focus-in effect is noticeable, it still looks professional.

Here's a video recording with Network bandwidth throttled:
https://www.youtube.com/watch?v=mydnPTIc-4g&feature=youtu.be - the quality has been greatly reduced when I uploaded the video on youtu.be - there's not much I can do about that, but you can clearly notice the effect in action.

I've used a simple gaussian blur effect for the thumbs and saved the large ones @100% quality on purpose, to make sure they don't load too fast (they are almost double in size compared to @80% - which is what you should normally use in production).

A typical element looks like this:

 <div class="item">
     <img src="./02-small.jpg"
          data-srcset="./02-medium.jpg 768w, 
                       ./02.jpg 1200w" 
          class="lazyload img-responsive" />
 </div>

If they still load too fast (and you don't notice the effect), go in developer console (on network tab) and limit (throttle) the network bandwidth.


With Angular, this would mean:

.carousel .img-responsive {
  min-width: 100%;
}
<div class="carousel slide">
  <carousel>
     <slide ng-repeat="i in imagesList">
        <img ng-src="./{{i.filename}}-small.jpg" 
             data-srcset="./{{i.filename}}-medium.jpg 768w,
                          ./{{i.filename}}.jpg 1200w" 
             ng-class="['lazyload', 'img-responsive']"
         />
     </slide>                                    
  </carousel>
</div>

In order to work, resulting urls should be pointing to existing files of different sizes and you might need to adjust the way you build each path, depending on your case.

Also, as @musicformelons pointed out in comments, lazyload class needs to be applied via ng-class. Applying it directly in markup makes Lazysizes instantiate too early, before Angular parses the urls, resulting in urls containing mustache notation (which obviously won't work).

like image 37
tao Avatar answered Oct 16 '22 00:10

tao


If you want to listen to the event where all the images in a certain component are loaded this library can help you do that - https://github.com/desandro/imagesloaded. When the images are loaded you can either initialize or reload the carousel.

$element.imagesLoaded( function() {
  // reload carousel
});

Sometimes, when loading a carousel it is also useful if you wait for the ng-repeat to finish rendering before initializing. You can take a look here for an explanation:

https://stackoverflow.com/a/39346023/1385281

like image 91
korun Avatar answered Oct 15 '22 23:10

korun