Is scroll position (scrollTop) hardware accelerated in browsers?

Viewed 6765

My initial guess is that the answer is no, because of evidence presented here:

https://github.com/inuyaksa/jquery.nicescroll/wiki/Native-scroll-vs-Hardware-accelerated-one

I can notice qualitatively that the "HW accelerated" version scrolls smoother on my computer. I run a 120Hz monitor. This suggests that the second method is faster and more efficient.

For an HTML element such as

<div id="a" style="overflow-y: hidden; height: 100px">
    Content <em>which exceeds 100px in height</em>
    <img src='lolcat.png' alt='lolcat'/>
</div>

I suppose a straightforward way for 3D hardware accelerated layout to be implemented is that the full height of the div is rendered and then this output is loaded as a texture of the full height, and then the texture coordinates used to render the actual div will reveal only 100px at a time.

My question is related to how the scrollTop property should in theory do this but it seems that at present there is a much better chance of obtaining the behavior I described by using TWO elements like so:

<div id="a" style="overflow-y: hidden; height: 100px; position: relative">
    <div style="position: relative">
        Content <em>which exceeds 100px in height</em>
        <img src='lolcat.png' alt='lolcat'/>
    </div>
</div>

Where instead of setting the scrollTop property of document.getElementById('a') I set the CCS3 -webkit/moz/ms/o-transform property to a 3D value with a corresponding negative Y-axis pixel value.

What's the most efficient way to do scrolling with CSS3? In particular, how can I structure my DOM to have the best chance of getting the most straightforward implementation of scrolling (not causing a re-draw of inner contents when scrolling an element)?

Update: I have been using a really nice smooth scroll plugin for Chrome, which seems to use JS to assign the scrollTop offset on the page to achieve the scroll rendering, which seems to indicate that if this were not hardware accelerated, the performance couldn't really keep up with the screen refresh rate (120Hz) without lots of CPU usage. Still, this kind of speculation remains extremely unscientific. The conclusion I'm going with at this point is that browsers have the freedom to accelerate anything that they choose to within reason so the answer is a resounding maybe.

3 Answers

scrollTop is not hardware accelerated. The best way I found that can generate a smooth scrolling even on a mobile device is to force a css3 hardware acceleration combined with a transition.

I'll assume you have jQuery so I'm using that syntax for clarity purposes, all I'm doing is setting css attributes and other basic calls.

var $body = $('body');
function scrollTop(scrollPosition) {
    // account for the current scroll position
    var scrollDiff = $body.scrollTop() - scrollPosition;

    // use css transition
    $body.css('transition', '.5s');

    // translate3d forces hardware acceleration, second param is 'y'
    $body.css('transform', 'translate3d(0, ' + scrollDiff + 'px, 0)');

    // revert back to native scrollTop
    $body.bind('transitionend webkitTransitionEnd', function(event) {
        $body
        .scrollTop(scrollPosition)
        .css({'transition': '', 'transform': ''})
        .unbind(event);
    });
}

Note: I did notice that the transitionend event isn't always reliable on mobile; this makes the "revert back to native scrollTop" portion of the code appear glitchy. I think the best approach is to take this further and implement your own scrollbar without using scrollTop. The second param of translate3d() divided by the height of the container will be the location (in percentage) of your scroller in terms of the trackbar.

Related