简体   繁体   中英

Strange / Inconsistent scrollTop behaviour

I stumbled into this one whilst trying to scroll an element without invoking the normal event handlers

Using both Firefox and IE10 I'm seeing some really strange behaviour in how the scrollTop method is operating. For example, if I set the scrollTop on a div , and aferwards , bind a scroll event handler to the same element, the handler fires immediately. From my testing, this doesn't happen with Chrome, which leads me to think that FF and IE are applying the most miniscule of animations to their scrolls, or this is some kind of bug.

See JSFiddle example . Interestingly, if I set a timeout of 1ms before the assignment, the problem goes away . I'd love to know what's going on here, and what the best approach is to fix it.

Update : From the comments below it seems as though this might be recognised to be normal browser behaviour, so I'll update my question to ask what is going on here - please cite some interesting articles which explain this process in more detail .

What goes on in IE and FF is the following:

  1. The scrollTop property is adjusted
  2. The scroll event handler is added
  3. Execution of the function finishes. Now, the browser has time for other things and will render the page. The rendering causes both the scroll handler and the scrollTop property to be committed simultaneously. The scrollTop change thus triggers a scroll event which is captured by your handler.

This is unlike this code:

var dv = document.getElementsByTagName("div")[0];
dv.scrollTop = dv.scrollHeight;
setTimeout(function(){
    dv.onscroll = function() { 
    console.log("scrolled!");
}, 0);

Where the following happpens:

  1. The scrollTop property is adjusted
  2. The setTimeout function appends the function that adds the onscroll event handler to the event queue. Essentially deferring the execution of the code until timeout processing occurs (see also the newer window.setImmediate).
  3. Execution of your function finishes. Now, the browser has time for other things and will render the page. The rendering will trigger a scroll event, but because your function was deferred, it has not yet been added and thus nothing captures the scroll event.
  4. Rendering the page finishes. Now, the browser has time for other things and will execute the function set by setTimeout. This will add the onscroll event handler, but since the scroll event has already been triggered, the event handler will not be called.

More information on the subject can be found here and here .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM