aFarkas / lazysizes

High performance and SEO friendly lazy loader for images (responsive and normal), iframes and more, that detects any visibility changes triggered through user interaction, CSS or JavaScript without configuration.
MIT License
17.49k stars 1.73k forks source link

scrolling on chrome - image does not load until the viewport stops scrolling #139

Closed geekyme closed 9 years ago

geekyme commented 9 years ago

I've checked out the demo and tested it on my mobile chrome http://afarkas.github.io/lazysizes/#examples

It appears the behavior for lazy loading is to start loading the image only after the view port have stop scrolling. It's quite an awkward experience because users will have to stop scrolling and wait for the images to load, rather than scroll and have the images start loading in parallel while the page is still scrolling.

aFarkas commented 9 years ago

To be honest I can not reproduce your experience. Is this also happening on your desktop browser or only for mobile? In case this happens only on mobile check out the following page (with your mobile browser): http://andyshora.com/mobile-scroll-event-problems.html (is scrollTop updated instantly while scrolling)

lazySizes only throttles the scroll event, it isn't debounced. Additionally lazySizes should start a download before an image is coming into view.

Maybe you can change by using the options. You could try:

window.lazySizesConfig = window.lazySizesConfig || {};

lazySizesConfig.throttle = 70; //default: 125
lazySizesConfig.expand = 500; //default: 360
lazySizesConfig.expFactor = 1.5; //default: 2
lazySizesConfig.loadMode = 3; //default 2
geekyme commented 9 years ago

oh crap yes its only on mobile. thanks for linking that article... in that case is there a workaround to make lazySizes load the images on mobile while scrolling?

aFarkas commented 9 years ago

You can try:

document.addEventListener('touchmove', lazySizes.loader.checkElems, true);

My question most modern smartphones should trigger scroll events while scrolling. What smartphone and android version are you using?

geekyme commented 9 years ago

i'm using iphone 6. and i'm using Google Chrome for iPhone. Not seeing the images load on http://afarkas.github.io/lazysizes/#examples until scrolling comes to a stop.

aFarkas commented 9 years ago

http://developer.telerik.com/featured/scroll-event-change-ios-8-big-deal/ https://code.google.com/p/chromium/issues/detail?id=423444

As already said you can try:

document.addEventListener('touchmove', lazySizes.loader.checkElems, true);
aFarkas commented 9 years ago

Or better:

document.addEventListener('touchmove', lazySizes.loader.checkElems, true);
document.addEventListener('touchend', function(){
    setTimeout(lazySizes.loader.checkElems, 300);
}, true);
geekyme commented 9 years ago

Hmmm have u added those event handlers in the demo site ?

On 7 Aug 2015, at 11:56 pm, Alexander Farkas notifications@github.com wrote:

Or better:

document.addEventListener('touchmove', lazySizes.loader.checkElems, true); document.addEventListener('touchend', function(){ setTimeout(lazySizes.loader.checkElems, 250); }, true); — Reply to this email directly or view it on GitHub.

aFarkas commented 9 years ago

no

geekyme commented 9 years ago

aight let u know once i've tried your suggestions !

geekyme commented 9 years ago

I've tried it out, putting those document event listeners did not help. Images still doesn't load until the scrolling stops. I'm not sure if you misunderstood what I meant, but basically what I want was for the images to load while while you scroll. The current behavior on the phone is to only load after the scrolling stops.

iOS iphone v8.3, chrome v44.0.2403.67.

geekyme commented 9 years ago

More details:

So i put a little box on the bottom left to track the touchmove events firing. Indeed when my finger is on the screen scrolling, the numbers are increasing. However, the images still do not show up until the screen has stop scrolling. I've attached a screenshot of how the screen looks like when it is still scrolling.

var scroll = 0;
window.addEventListener("load", () => {
  var el = document.createElement("div");
  el.setAttribute("style", "background:red;padding:10px;position:fixed;bottom:0;color:white;");
  el.setAttribute("id", "testtest");
  document.body.appendChild(el);
  document.getElementById("testtest").innerHTML = scroll;
});

// allow lazy loading on momentum scroll ?
document.addEventListener('touchmove', function(){
  Lazysizes.loader.checkElems();
  scroll = scroll + 1;
  document.getElementById("testtest").innerHTML = scroll;
}, true);

document.addEventListener('touchend', function(){
  setTimeout(Lazysizes.loader.checkElems, 300);
}, true);

image

aFarkas commented 9 years ago

I'm going on vacation for two weeks, so I can't help you until then.

aFarkas commented 9 years ago

Sorry for not helping. This is a constrain of the iOS webview, which is used by Chrome on iOS (It isn't actually a blink engine).

While scrolling the webview doesn't paint any DOM changes.

geekyme commented 9 years ago

I see. Ok thanks

Sent from my iPhone

On 23 Aug 2015, at 6:40 pm, Alexander Farkas notifications@github.com wrote:

Sorry for not helping. This is a constrain of the iOS webview, which is used by Chrome on iOS (It isn't actually a blink engine).

While scrolling the webview doesn't paint any DOM changes.

— Reply to this email directly or view it on GitHub.

epoberezkin commented 7 years ago

The same happens on MacOS in chrome (desktop) if you scroll with touch pad (or with mouse touch). Scroll events fire, requests for images show as pending, but the images are loaded after scrolling stops (and the load time shows as <5ms).

Works ok if you scroll by dragging scrollbar

Works ok in safari.

aaronorosen commented 7 years ago

I just hit this issue too. fwiw here's the solution I used and it seems to work pretty well.

    var scrollStarted = false;
    var scrollLooper = null;        
    document.addEventListener('touchmove', function(){                                                                        
        scrollStarted = true;
        scrollLoop = setInterval(function() {                                                                                 
            $(window).trigger("scroll");                                                                                      
        }, 100) 
    });     
    document.addEventListener('touchend', function(){                                                                         
        scrollStarted = false;
        $(window).trigger("scroll");                                                                                          
        setTimeout(function() {                                                                                               
            if(scrollStarted == false) {                                                                                      
                clearInterval(scrollLooper);                                                                                  
            }                                                                                                                 
        }, 1000);                                                                                                             
    });
richardcalahan commented 7 years ago

@epoberezkin indeed it happens on Chrome on MacOS desktop. I found that if you give the img explicit dimensions, either in px or %, the issue goes away.

Youfka commented 7 years ago

have this issue on desctop Chrome and Opera(windows), solutions by aaronorosen and richardcalahan don't help. Images don't load until I stop scrolling, but only when I do it with mouse wheel. When I drag scrollbar it's ok

kylemacfarlane commented 7 years ago

I ran into this problem just using plain old IntersectionObserver (never used lazysizes) but this GitHub issue is the only place I can find talking about it.

It looks like Chrome updates the DOM (and downloads the image in the background) but sometimes doesn't actually draw the image until scrolling has stopped. For me it:

  1. Doesn't happen on my Windows desktop.
  2. Doesn't happen on a Toshiba Chromebook 2 either with touchpad or scrollbars.
  3. Happens maybe 20% of the time on a Nexus 7.
  4. More like 50% of the time on an old Moto G.
  5. It seems to be affected by how long Chrome has been running and how long the page has been loaded (i.e. give both time to fully load up and settle down).
  6. However if I connect a remote debugging session to Android it happens all the time.
  7. But it doesn't happen when recording performance or running an audit from the remote debugger.
  8. It seems to be less likely to occur if the images are already cached.

Basically I think it's a performance optimisation in Chrome and will only show up on slower devices. Giving the image explicit dimensions will reduce the chance of a DOM reflow so might reduce the issue but not eliminate it.