Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 766
Ian Clark Avatar asked Nov 04 '13 11:11

Ian Clark


People also ask

How do you stop an Onscroll event?

onscroll event fires when the window has been scrolled. Overriding this function and setting it to a fixed position every time the scroll happens will effectively disable the scroll effect. The current scroll position from the top is found by using the window. pageYOffset and the document.

What is Onscroll event?

The onscroll event occurs when an element's scrollbar is being scrolled. Tip: use the CSS overflow style property to create a scrollbar for an element.

How scrollTo works?

The method scrollTo(pageX,pageY) scrolls the page to absolute coordinates, so that the top-left corner of the visible part has coordinates (pageX, pageY) relative to the document's top-left corner. It's like setting scrollLeft/scrollTop . To scroll to the very beginning, we can use scrollTo(0,0) .

What is window scroll?

The Window. scroll() method scrolls the window to a particular place in the document.


1 Answers

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.

like image 54
Borre Mosch Avatar answered Oct 04 '22 17:10

Borre Mosch