Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is scroll position (scrollTop) hardware accelerated in browsers?

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.

like image 453
Steven Lu Avatar asked Aug 17 '12 23:08

Steven Lu


People also ask

What does scrollTop mean?

An element's scrollTop value is a measurement of the distance from the element's top to its topmost visible content. When an element's content does not generate a vertical scrollbar, then its scrollTop value is 0 .

How do you control the scroll position?

To get or set the scroll position of an element, you follow these steps: First, select the element using the selecting methods such as querySelector() . Second, access the scroll position of the element via the scrollLeft and scrollTop properties.

What method allows you to get the vertical position of the scroll bar for an element?

The scrollTop() method sets or returns the vertical scrollbar position for the selected elements.


2 Answers

According to the page you mentioned, hardware acceleration depends on if the browser supports hardware acceleration.

Div with wrapper can be hw accelerated. (if browser support it)

So I think your idea of nesting two divs will create an easier way of achieving what you want. But to answer your question, scrollTop is only hardware accelerated in browsers that support hardware acceleration.

  1. Firefox 4.0 beta 5 supports HW acceleration.
  2. IE 9 beta supports HW acceleration.
  3. Chrome 6+ supports HW accelerated composition.

Safari and Opera have yet to support hardware acceleration.

This is according to this page from 2010. http://www.webmonkey.com/2010/09/a-guide-to-hardware-acceleration-in-modern-browsers/

According to http://arstechnica.com/information-technology/2012/06/opera-12-arrives-with-webcam-apis-and-experimental-webgl-support/, Opera 12 supports hardware acceleration.

According to TechCrunch, Safari 5 for Windows supports hardware acceleration.

According to Apple Safari's website, Safari 6 supports hardware acceleration.

Sorry! I had links to the TechCrunch article and Safari's website, but I can only use two hyperlinks.

EDIT:

In order to answer the question better, I add to the question. The most efficient way to do scrolling with CSS3 is overflow: scroll; or overflow-x: scroll;. The overflow: CSS property is more efficient CSS than scrollTop because scrollTop is a jQuery tag, which uses JavaScript. So using scrollTop isn't CSS, it's JavaScript. Also, using CSS is also the most straightforward method of achieving horizontal scrolling because it doesn't require importing jQuery library or having JavaScript enabled.

I completely agree with you by saying that there's a much better chance of obtaining the behavior you described by using two div tags and CSS instead of using jQuery/JavaScript.

Unless, you want to be able to automatically scroll to another location, when using scrollTop you can effectively scroll to different locations by using a button or link.

$(document).ready(function() {
    $('a[href=#top]').click(function(){
        $('html, body').animate({scrollTop:0}, 'slow');
        return false;
    });
});

This jQuery code using scrollTop makes all <a href="#top">top</a> animate the scroll to the top instead of just jumping. When using CSS to scroll, you don't get these animated scrolls. Also, you could use this method to scroll to a different point horizontally or vertically by setting the ID of multiple div tags and editing the above code to suit your needs. This is from http://www.electrictoolbox.com/jquery-scroll-top/.

like image 65
gtr123 Avatar answered Oct 02 '22 21:10

gtr123


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.

like image 41
EnotionZ Avatar answered Oct 02 '22 22:10

EnotionZ