22

If we make a simple test case like:

document.documentElement.addEventListener('scroll', function() {
    console.log(document.documentElement.scrollTop);
});

And then go and scroll using the scrollbar by clicking the track, or by using PageDown/PageUp, then we can see that we only get one event at the end of the scrolling animation.

Now theoretically I could fix some of that behaviour by simulating the scroll events. Example code with jQuery and Underscore:

$(function () {
    var $document = $(document), until = 0;

    var throttleScroll = _.throttle(function () {
        $document.scroll();
        if (+new Date < until) {
            setTimeout(throttleScroll, 50);
        }
    }, 50);

    $document.keydown(function (evt) {
        if (evt.which === 33 || evt.which === 34) {
            until = +new Date + 300;
            throttleScroll();
        }
    });
});

But it still does not work. We only get scroll events with the original scrollTop and the destination scrollTop, no values in between.

If then go and console.log(document.documentElement.scrollTop) every 10ms, then we can see that IE just does not update the scrollTop as it scrolls.

This is very frustrating if we want to "pin" something to the scroll position. It gets jerky with IE.

I did not observe this behaviour on any other browser, and did not test with previous IE versions.

If anyone has found a way to fix IE's behaviour (maybe there's a magic CSS to turn off smooth scrolling in IE 11?) then I would very much like to hear about it!

Thanks :-)

daniel.gindi
  • 3,457
  • 1
  • 30
  • 36
  • Nothing ah? Thought so. – daniel.gindi Feb 16 '14 at 17:34
  • This is old, but I've run into the exact same issue. I tried using setInterval and forcing the function to update at 60fps, but that just made it noticeably jittery on all browsers. Plus it didn't seem to make a difference on IE :\ – Jason Jul 30 '14 at 16:11
  • After some more fiddling, I've found that the best way to the jerkiness is to use `position:fixed` as much as possible instead of `position:absolute` with a manual `top`. It's definitely a rendering bug in IE. It doesn't present itself as much with smooth scrolling disabled, but it's still somewhat jerky. Plus, smooth scrolling is enabled by default, so almost all IE users will notice the problem. – Jason Jul 30 '14 at 17:03
  • My issue was not with fixed elements, but with virtual tables... You just cannot render the new cells when scrolled. IE, as usual, sucks. Even after 10 versions. – daniel.gindi Jul 30 '14 at 20:20
  • "I did not observe this behaviour on any other browser" - iOS Safari has behaved like this since the day it was first released. I suspect the IE team feel they can follow that precedent if it gives them a performance edge. Android Chrome sends scroll events fairly frequently, but not enough to get rid of jerkiness. – stephband Aug 04 '14 at 22:48
  • Mobile Safari does this only when scrolling mode is set to "touch". – daniel.gindi Aug 05 '14 at 05:38
  • Nope, iOs Safari dont trigger scroll event when scrolling, stephband is right, iOS lock JavaScript until scroll end. @daniel.gindi, you have to possibility: Recreate the smooth scroll by listening mousewheel, prevent default, then animate the scrollTop. Or you can use a setInterval() (but requestAnimationFrame() is better) – Jordan Aug 25 '14 at 10:42
  • I'm not sure though that we can capture all scroll triggers and replace with manual ones. Will try... – daniel.gindi Aug 25 '14 at 10:44
  • @daniel.gindi What version of IE are you seeing the issue with? I created this [JSBin][http://jsbin.com/wukuna/4/] to look at the frequency of updates to `scrollTop` and the `scroll` event. I tried it in IE11 (desktop and metro, touch and trackpad) and IE10 with a mosue, and IE9-mode (on IE10) with a mouse and it updated *very* frequently. – pseudosavant Aug 27 '14 at 18:46
  • IE11. I guess that smooth scrolling is disabled in your installation for some reason. – daniel.gindi Aug 27 '14 at 19:11
  • Actually smooth scrolling is enabled on all of them. I checked before I did my test. Do you experience the issue when you try the JSBin link I mentioned? – pseudosavant Aug 27 '14 at 21:03
  • Yes I did. This happens when you CLICK the TRACK, to cause smooth scrolling. Not when you manually scroll. – daniel.gindi Aug 28 '14 at 05:15
  • IE10 on win8, IE11 on win 8.1 both has this issue. – Andrey Dec 02 '14 at 00:13
  • Just encountered a similar issue. I would like an answer to this problem myself – scooterlord Apr 15 '15 at 10:44

4 Answers4

9

You said: "If anyone has found a way to fix IE's behaviour (maybe there's a magic CSS to turn off smooth scrolling in IE 11?) then I would very much like to hear about it!"

This does not turn it off, but here is what I use to resolve the smooth scroll issue in ie with Fixed elements.

if(navigator.userAgent.match(/Trident\/7\./)) {
    $('body').on("mousewheel", function ( event ) {
        event.preventDefault();
        var wd = event.wheelDelta;
        var csp = window.pageYOffset;
        window.scrollTo(0, csp - wd);
    });
}
jhadenfeldt
  • 194
  • 2
  • 13
M H
  • 2,179
  • 25
  • 50
  • Seems nice - stops IE 11 from continuing the scroll... Did you try to create a solution that fixes the page up/down too? – daniel.gindi Jun 02 '15 at 19:52
  • 1
    If we could add support for touch based (swipe) scrolling, keyboard up/down and trackpad that would be amazing. The error I get it on is with using background-attachment: fixed. – patrickzdb Jun 03 '15 at 15:32
6

The issue you're describing is limited to instances of Internet Explorer 11 running on Windows 7. This problem doesn't affect the platform upon which IE 11 was born, Windows 8.1. It seems as though IE 11 on Windows 7 falls into a similar category as other scrolling implementations mentioned above. It's not ideal, but it's something we have to work with/around for the time being.

I'm going to continue looking into this; in fact, just dug a Windows 7 machine out of the closet to setup first thing in the morning so as to investigate further. While we cannot address this head-on, perhaps, maybe, there's a way we can circumvent the problem itself.

To be continued.

Sampson
  • 265,109
  • 74
  • 539
  • 565
  • It sounds like... You are from the IE team? Or am I mistaken? Anyway - any effort is appreciated! And I'm sure not just by me... As this is a big limitation on possible functionality. (Virtual tables etc.) – daniel.gindi Nov 18 '14 at 08:08
  • 1
    @daniel.gindi Yes, I am a Program Manager on the Internet Explorer team. If you have a demo that breaks as a result of this, I would appreciate a link. Something to experiment with would make further investigation more fruitful. – Sampson Nov 18 '14 at 08:21
  • Great! Well there's the test page for my amazing table js for Backbone. https://raw.githack.com/danielgindi/DGTable.js/master/example/example.html You can see that while scrolling - the rows that are supposed to fill the space are white, because they don't exist yet. In this demo the buffer is big but still not enough to cover for the IE smooth scrolling... – daniel.gindi Nov 18 '14 at 08:57
  • IE10 on win8, IE11 on win 8.1 both has this issue. I.e. see http://bigspotteddog.github.io/ScrollToFixed/ and try to scroll back and forth by 1 tick with mouse wheel to pin/unpin elements - they will stay unpinned until the end of scroll animation, then jump to proper position when scroll event finally fired. – Andrey Dec 02 '14 at 00:19
  • @Andrey Perhaps we're looking at different issues? The [earlier fiddle](http://jsbin.com/wukuna/4/]) shows the issue on IE 11 with Windows 7, but not with IE 11 on Windows 8.1 I just sat down on two machines and tried it again to be certain. – Sampson Dec 02 '14 at 00:47
  • 2
    @Jonathan Sampson as far as I understood, the issue is about IE11 not firing scroll event during smooth-scroll animation. So that we see page scrolling animation but we not get scroll event during this animation so all stuff that needs updating on scroll event is not actually updating, it is updated instantly only at the end of the animation, when scroll event is fired. This gives us that jerky behavior when page was already animated and stuff that needs to be updated just jumps in place after animation. – Andrey Dec 02 '14 at 01:45
  • 1
    @Jonathan Sampson On Win 8 and IE 10.0.9200.16384 I see this fiddle not updating div text during animation. See: http://goo.gl/tYYilU On Win 8.1 and IE 11.0.13 this fiddle is updating div text during animation, but in real world example there is still a jump during scroll animation, see: http://goo.gl/7qfPkc , which means that maybe during animation scroll events dispatched with insufficient rate or something, but there is clearly some problem with it in IE11 on win8.1. Comparing to Firefox smooth scrolling, element pins smoothly, like we just drag scrollbar by hand: http://goo.gl/h07Ty8 – Andrey Dec 02 '14 at 01:45
  • 1
    @Jonathan Sampson, more clear example: http://jsbin.com/bulivizozi/1. Here we also update top position of the element. On Win 8.1 and IE 11.0.13 element jitters while scroll is animating, despite the fact that scroll events are firing. Element does not jitter if we drag scrollbar by hand: http://goo.gl/wliFqV . But I am using win 8.1 from modern.IE VM, and did not update it for a while. Maybe this is not the issue on the newest windows builds... – Andrey Dec 02 '14 at 02:08
  • @JonathanSampson any news on that? – daniel.gindi Mar 13 '15 at 12:04
1

As a crazy last resort (seems not so crazy actually if the issue is critical) - maybe turn off native scrolling completely and use custom scrolling (i.e. http://jscrollpane.kelvinluck.com/)? And bind onscroll stuff to its custom events: http://jscrollpane.kelvinluck.com/events.html

Andrey
  • 1,018
  • 12
  • 21
  • Yes that could be a solution ( or a hack ) and I'm going to have to make some tests to see how it handles touch events... – daniel.gindi Dec 02 '14 at 05:03
-1

Looks like there's a post on IE and forcing a screen "paint" to help with drag-drop. Seems the opposite of most performance efforts but might work? https://stackoverflow.com/a/12395506/906526 (code from https://stackoverflow.com/users/315083/george)

function cleanDisplay() {
    var c = document.createElement('div');
    c.innerHTML = 'x';
    c.style.visibility = 'hidden';
    c.style.height = '1px';
    document.body.insertBefore(c, document.body.firstChild);
    window.setTimeout(function() {document.body.removeChild(c)}, 1);
}

You might try CSS animations so the browser handles animation/ transition. Eg applying a show/ hide class on scroll and, CSS animation.

.hide-remove {
    -webkit-animation: bounceIn 2.5s;
    animation: bounceIn 2.5s;
}

.hide-add {
    -webkit-animation: flipOutX 2.5s;
    animation: flipOutX 2.5s;
    display: block !important;
}

If not having a browser handle animation (with creative css), keyframes and JS performance might offer leads. As a plus, I've seen several sites with navigation bars that "reappear" after scroll end.

Community
  • 1
  • 1
s6712
  • 496
  • 5
  • 14
  • How would that help? Redrawing has nothing to do with scrolling. And if that *would* work, do you propose causing the browser to redraw every X milliseconds, whether it's scrolling or not? – daniel.gindi Sep 03 '14 at 06:25
  • I understood the issue as "moving the menu" looks jerky so was suggesting redrawing for positioning information. All browsers move in large hops when wheel scrolling. – s6712 Sep 03 '14 at 15:40
  • No, the issue is NOT GETTING JAVASCRIPT ONSCROLL EVENTS. – daniel.gindi Sep 03 '14 at 18:41