Be careful how you apply your hardware accelerated CSS3 transitions


speedy2

I have been experimenting a lot with HTML5, JavaScript and especially CSS3 on a variety of mobile devices recently. I want the mobile applications that we build with web technologies to continue to provide all the cross platform and deployment benefits that our clients have been enjoying with our desktop based trading apps, but I want them to continue to look great, I want them to continue to provide the user with a fantastic experience and in order to do so they must perform well.

As Sencha has shown with their FastBook demo it is more than possible to make mobile web based applications that look and feel as good, if not better than their native counterparts, but it is fair to say that in order to do so you need a deep understanding of the languages, browsers and design patterns that you are using.

So although we have many years of experience building complex, real-time trading applications in the browser we never stop experimenting, especially with new mobile devices, and my more recent experiments have been with hardware accelerated CSS properties on mobile.

Hardward accelerated transitions : The classList problem

As detailed in Paul Lewis and Paul Irish’s post High Performance Animations, the four things a browser can animate cheaply are:

  • transform (both 2d and 3d)
  • scale
  • rotate
  • opacity

I have had a great time with these properties, by combining them you can create almost any transition that you will find in popular native applications and they perform very well.

But I noticed a surprising issue, especially when translating complex DOM trees which I didn’t expect as the transition should be handled by the GPU (and is). The transition was always silky smooth but with complex trees there was a long delay before the transition begun. The problem got worse with larger trees.

Taking a look at the chrome console the delay was being caused by an expensive Recalculate Style. This was being triggered because to initialise the transition I was adding a class to my container element.

element.classList.add("transition");

Even though the ‘transition’ class only contained a single property that shouldn’t really need to cause an expensive Recalculate Style it was happening anyway becuase I added a class.

Moving the property modification into JavaScript resolved the issue.

element.style.webkitTransform = "translate(500px, 0)";

The issue can be seen at the codepen I put together.

http://codepen.io/stevesouth/full/xcfGk

Note: There is a JavaScript variable treeDepth which unsurprisingly controls the size of the large DOM trees. For the timeline below i had this set to 100000 and tested in Chrome. Firefox seemed to crash at anything above 20000, IE11 was OK. If you experience this issue you can load the pen with JS disabled by adding ?turn_off_js=true to the url which gives you a chance to change the parameter. You shouldn’t need to go so high to see the difference in the Chrome timeline.

The following timeline screenshot shows the issue perfectly.

timeline-skitch

Clicking each of the four elements in a row, it is clear from the timeline that there is an expensive Recalculate Style happening when you click the third element. This is eliminated when the style modification is moved from a class to a JavaScript modification.

Other Browsers

Although this post has been heavily focussed on Chrome, I have ensured that the codepen works in the latest version of IE and Firefox. Safari should be fine too, however I haven’t done much investigation into how any of these browsers behave yet, please comment below if you find out.

In summary…

If you are experiencing delays with your transitions check the Chrome timeline, see if some unnecessary Recalculate Styles are firing and if so you might want to make a similar change. Most great animations libraries such as animate.css use classes, which makes perfect sense, but could lead to the issue above.

Saying all this, please don’t leave this post just thinking ‘Classes bad, JavaScript good’ for this use case. I agree with Paul Lewis that in general you should be thinking ‘tools not rules’ and I would recommend you take a look at his Guide to Rendering Performance presentation.

It may well be that browsers resolve this issue in the future, I am not sure why they couldn’t already know that adding the ‘transition’ class doesn’t require a Recalculate Style. So at some point my advice above will hopefully becomes completely useless. Unless that is, you start using the Chrome timeline a bit more.

Related Posts with Thumbnails

6 Comments

  • Jake says:

    this is such a great article!

    wonder why no one has left a reply to it :(

  • Joe Rhoney says:

    This is really eye-opening. I’m all in favor of using class changes, so I do hope the browser developers handle this issue. Glad we can at least use class changes on a shallow level without much trouble still.

    Thank you for sharing this impressive (and needed) research!

  • thanks a lot, this is very useful to know for my React Phonegap application :) I have some transition problems on pane swipes

  • Matjaz Jurecic says:

    Hi, great article.

    I have a question. I have a large table with 10k rows and currently I am setting transformation to a specific class in the table. This is really slow. Do you maybe have a suggestion for this problem?

    One solution is to render only the elements visible or let say some length of elements, that it still works ok, but if there is a simpler solution then that.

    THX.

    var headRows = jqElm.find(‘.BigTable-StickyCol’);
    jqElm.find(‘.BigTable-Grid tbody’).on(‘scroll’, function (e) {
    if (prevScrollTop !== e.target.scrollTop) {
    prevScrollTop = e.target.scrollTop;
    headRows.css({
    transform: ‘translateY(‘ + (-prevScrollTop) + ‘px)’,
    MozTransform: ‘translateY(‘ + (-prevScrollTop) + ‘px)’,
    WebkitTransform: ‘translateY(‘ + (-prevScrollTop) + ‘px)’,
    msTransform: ‘translateY(‘ + (-prevScrollTop) + ‘px)’
    });
    }
    });

  • Overall, from a performance point of view, the iPhone 7 is a huge improvement over the iPhone 6S, which is admirable as the iPhone 6S was a hell of a phone.

Leave a Comment

*
To prove you're a person (not a spam script), type the security word shown in the picture. Click on the picture to hear an audio file of the word.
Anti-spam image