“onscroll” fired after or before repaint?

2019-04-07 03:27发布

I have a scrollbar on a div element.

On many browsers (I tested this on recent versions of Chrome and Firefox on MacOS and Linux), it seems like the browsers make sure that code bound to onscroll is called before the repaint trigger by the scrolling.

In other words, the following fiddle does not flicker nor blink when scrolling http://jsfiddle.net/m2E65/1/ :

var onscroll = function() {
    var y = $("#container").scrollTop() + 30;
    var z = 0
    for (var c=0; c<y*10000; c++) {
        z+=c;
    }
    $("#label").text("bocal : "+z);
    $("#label").css("top", y);
};
$('#container').scroll(onscroll);

However on Linux Chromium v28 on Ubuntu, it does flicker. Almost as badly as if we deferred onscroll using setTimeout (http://jsfiddle.net/m2E65/2/) :

$('#container').scroll(function() {
    window.setTimeout(onscroll, 0);
});

On this very same browser, even using requestAnimationFrame as in http://jsfiddle.net/m2E65/4/ flickers just as badly (see below)

var onscroll = function() {
    var y = $("#container").scrollTop() + 30;
    var z = 0
    for (var c=0; c<y*10000; c++) {
        z+=c;
    }
    $("#label").text("bocal : "+z);
    $("#label").css("top", y);
    window.requestAnimationFrame(onscroll);
};
window.requestAnimationFrame(onscroll);

My question is :

  • Is there a spec for this?
  • Is there a way to ensure that on all browsers, the code will be run before repaint?
  • Bonus point : how rare is this behavior?

1条回答
走好不送
2楼-- · 2019-04-07 04:22

1. Out of Document Object Model (DOM) Level 3 Events Specification W3C Document:

A user agent must dispatch this event when a document view or an element has been scrolled. This event type is dispatched after the scroll has occurred.

My interpretation of this two sentences is that a browser has to dispatch the scrollevent after the scroll process completed inclusive repainting.

2. I don't think there is way to ensure that on all browsers, the code will fire before repaint. Maybe you could try catching all ways a user can scroll, spontaneous I thought of:

  • a mouse wheel -> the wheel event
  • by selecting text -> mousedown
  • using a scrollbar -> you can just hope that mousedown will fire.

3. Your first fiddle flickers to me on:

  • Safari 7.0.1
  • Safari on iOS 7
  • As you said in Chrominum on Ubuntu

It does not flicker in:

  • Firefox 27.0 Mac and Ubuntu
  • Opera 19.0 Mac
  • Chrome

Now it think that specially WebKit-Browsers (except Chrome) not repaint before calling the scrollevent and that there is no good way to prevent this.

查看更多
登录 后发表回答