Jump to content
Search Community

top: left: versus x: y: ?

mintervals test
Moderator Tag

Warning: Please note

This thread was started before GSAP 3 was released. Some information, especially the syntax, may be out of date for GSAP 3. Please see the GSAP 3 migration guide and release notes for more information about how to update the code to GSAP 3's syntax. 

Recommended Posts

Yes and no.


The problem is that in browsers like Chrome, each translated element is put on its own rendering layer. It takes time to create these layers and the more layers you have the more costly each update becomes. So if you are animating only a few elements, using transforms may yield better results BUT there will a point where the gains will diminish noticeably.


Our speed test has been configured to allow you to compare 


top/left/width/height tweens to translate/scale. 


Give it a run here:



Another thing to consider is that Safari for iOS does an incredible job with transforms. 

  • Like 1
Link to comment
Share on other sites

I'm pretty sure you read an article by Paul Irish, some time ago ot was asked by another forum user and Jack gave a solid answer in the matter, you can read it here:




As you can see is something that should be decided depending on the scenario you're facing, maybe for a small amount of short animations it might be a better solution.


Also keep in mind if you want to keep the document flow intact or not when you're animating a specific element, for more on that read the following:





Hope this helps,



  • Like 1
Link to comment
Share on other sites

And just to clarify, 3D transforms are treated by most browsers differently than 2D transforms. What Carl said above applies to 3D transforms, not necessarily 2D.


Desktop browsers have come a long way in being able to do top/left stuff fast (they used to be pretty slow). In our speed tests on desktops, top/left is often faster, but they're also limited to whole pixel values whereas translate (x/y) can do sub-pixel rendering in most browsers. 


There's no specific rule that always applies because it depends on many factors including how your page is built, which browser, if the machine has a decent video card, etc. 


Transforms perform terribly on IE8 too (not that I'm advocating that you build things to please IE8)

Link to comment
Share on other sites

Ok, here's an obvious approach -- not sure how it stacks up against the gs default matrix tween:

var el = $('#el'), 
    props = {x: 0, y: 0},
    style = el[0].style;

TweenMax.to(props, 0.7,
    {x: 100, y: 100, ease:Back.easeInOut.config(1),
        onUpdate: function(){
            style.WebkitTransform = 'translate3d(0px, ' + props.y + 'px, 0)';                
Link to comment
Share on other sites



In fact it's been said in the forums that triggering a 3D transform would optimize the animations, but that's only in some cases. The point is that forcing a 3D transform pushes the GPU to "kick in" so to speak, which can improve performance, but if you have a lot of tasks running, some other tabs in your browser and a lot of elements being animated it could backfire because you're putting too much on both the browser and the GPU. Jack gave a great explanation in the following posts:





In that same matter he added a new feature in the CSS plugin to force a 3D transform and get the GPU involved, you can read about it and download the plugin's preview here:



Now regarding the code you posted I'm pretty sure it wouldn't have any effect whatsoever. You could achieve the same effect with the following:

var el = $("#el");

TweenLite.to(el, 1, {y:100});

In your code you're using the engine to tween two values, then using an onUpdate call you pass one of those values and apply it through a javascript object and finally to the element, while using the engine to animate the y transform of the element. Also if you want some better performance you could use the CSS plugin preview and force a 3D transform, like this:

var el = $("#el");

TweenLite.to(el, 1, {y:100, force3D:true});

Hope this helps,



  • Like 1
Link to comment
Share on other sites

thanks for the response, Rodrigo!


I'm aware of how 3d transforms will kick in the GPU. My question was a little different than the original question - perhaps I should have started a different thread.


To clarify, the code you wrote above: TweenLite.to(el, 1, {y:100});


would result in the el's style attribute being updated every tick with a new transform matrix;


I was looking into the performance of a transform matrix vs translate3d - both of which trigger the GPU, but seem to have different performance as far as setting the elements attribute goes. have a look at the results for matrix, matrix3d, and translate3d here: http://jsperf.com/translate3d-vs-xy/49

Link to comment
Share on other sites

Thanks for the great discussion. For my project and the future I've now found out why NOT to use x: and y:


I have jQuery click functions on div's etc and if they've been moved around with x: and y: the click functions cease to work on older devices and possibly older browsers. I'm assuming the click listeners are not moving with the transforms. 


My navigation and menu etc doesn't work on ipad1 but does work on newer tablets and phones. 

Link to comment
Share on other sites

Hi Majman, you're welcome.


What I know is that the engine as it is right now is highly optimized and currently uses the transform properties instead of matrix and/or matrix3D. Here's a couple of lines if the CSS plugin:

 else if (!t.rotationY && !t.rotationX && a33 === 1) { //if we're only translating and/or 2D scaling, this is faster...

style[_transformProp] = "translate3d(" + t.x + "px," + t.y + "px," + t.z +"px)" + ((sx !== 1 || sy !== 1) ? " scale(" + sx + "," + sy + ")" : "");

Also one thing I've being reading consistently in the forums is the fact that the mind set of the staff is performance goes first, so everyone can rest in the fact that if there's a better way to do things they're already looking at it.




Link to comment
Share on other sites

I was digging around on jsperf to see how translate3d compared to matrix transforms, and it seems that translate3d wins out pretty consistently:




Jack, I don't suppose you know of a non-trivial way to default to translate3d when a tween is only using xyz props?  


Unfortunately, that jsperf is a very poor way to measure performance. Quite inaccurate, I'd say. One problem has to do with the fact that animation is a completely different beast than just running functions a bunch of times on a single frame/render and measuring how long it takes. When you alter a style by setting "top" or "left" or "transform" or whatever, that basically invalidates the style and tells the browser that next time it renders the screen, it needs to calculate the new styles and figure out how they affect layout and document flow. If you then alter another style property and it's already marked as "dirty" (in need of recalculation next render), it doesn't have to do much - it just sets the value and lets the browser manage when all the recalculation/layout/reflow happens. 


See the problem? 


If I set style.left 10,000 times in a loop, the browser still only has to perform the actual recalculations once when it renders the next frame visually. 


Setting top/left can affect document flow whereas setting transforms don't, so some work can be skipped in the case of transforms, but you'll only see those savings when the browser actually renders the changes to the screen. 


A true test of animation performance must involve screen renders and fps - that's what matters in terms of getting smooth results and minimizing CPU/GPU load. Synthetic jsperf loops don't show this. 


Another problem is that on all the transform-related portions of the test, you're setting 4 EXTRA (non-existent) properties! In other words, if you're in a Webkit browser, that code is still setting the Mozilla, Microsoft, Opera, and standards-based properties on the style element. That's quite wasteful and skews the results unfairly. 


Lastly, we've seen the best performance overall in the various browsers when we feed in a pure matrix() or matrix3d() value if there's any kind of rotation involved because that saves the browser from having to do that calculation itself. The values end up as a matrix either way in order to send to the GPU and render. Rotation is particularly time-consuming to calculate and render. As pointed out earlier in this thread, GSAP does actually use a translate3d() and/or scale() when no rotation or skew is involved because those are slightly faster. 


If you truly want to test animation performance, I'd highly recommend doing it across many frames and allowing the browser to render things along the way - don't just loop through JS code. One example can be found at http://www.greensock.com/js/speed.html, but you can do a much simpler one. 


Does that clear things up? 

  • Like 4
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Create New...