Search code examples
cssanimationbackground-position

CSS background-position: animating and performance


I've seen many examples for animating the background-position of elements to produce nice looking scrolling backgrounds.

These examples tend to also script in reset counters to put the background-position in its original location after a certain amount of pixels.

My question is: Is it feasible to never reset the background-position for a tiled background? This would naturally produce very large background-position values over time, but if there is no significant difference in browser performance, it might be ok. I've tested IE, Firefox, and Chrome over an 8 hour period, and there didn't appear to be any negative impact, although my boxes are relatively fast.

To answer the "why not reset?" question, it just comes down to simplicity. I am animating many background elements, each with different X/Y ratios, so not having to calculate when exactly it would be pixel perfect timing to switch back would make my life easier.

Anyone have thoughts on this?


Solution

  • This would naturally produce very large background-position values over time

    Yes, that could eventually become a problem if your code is like

    el.style.backgroundPosition= '0 '+n+'px';
    

    When n reaches a high number (typically 1000000000000000000000), its toString will switch to exponential representation, which would end up trying to set:

    el.style.backgroundPosition= '0 1e21px';
    

    which is an obvious error. It's possible some layout engines might bail out earlier, perhaps at 1<<31 pixels. But even so, if you were animating something by (say) 32 pixels 60 times a second, it would still take twelve days to reach that stage.

    not having to calculate when exactly it would be pixel perfect timing to switch back would make my life easier.

    Typically you'd use the modulo operator % separately on each counter rather than resetting the whole thing.

    var framen1= 30;     // item 1 has 30 frames of animation
    var framen2= 50;     // item 2 has 50 frames of animation
        ...
    var framei1= (framei1+1)%framen1; // 0 to 29 then reset
    var framei2= (framei2+1)%framen2; // 0 to 49 then reset
    

    Or, for time-based animations:

    var frametime1= 100; // item 1 updates 10 times a second
    var frametime2= 40;  // item 2 updates 25 times a second
        ...
    
    var dt= new Date()-t0; // get time since started animation
    
    var framei1= Math.floor(dt/frametime1) % framen1;
    var framei2= Math.floor(dt/framelength2) % numberofframes2;
    
    document.getElementById('div1').style.backgroundPosition= '0 '+(framei1*24)+'px';
    document.getElementById('div2').style.backgroundPosition= '0 '+(framei2*24)+'px';
       ...