Simulating the behaviour of iOS apps trough CSS animations is one of the key points of frameworks such as jQuery Mobile, Sencha, etc. Indeed, both in Mobile Safari and inside a webView (for instance with PhoneGap), CSS animations are hardware accelerated so their performances are really good.

But while I was developing my own project, the Lottery roulette app, I faced some serious problems with transitions’ performances, so I decided to analyse them. As you are going to read, the transitions on the iOS platform could have some serious problems caused by custom Webkit proprieties.

How iPhone CSS transitions stop running smoothly

One of the Lottery roulette app’s features is to animate a few columns of simple text along Y axis. I started developing my app on my desktop with Safari. I chose this method because it is easier to debug Javascript and CSS on Safari than on the iPhone.

When I thought that the app was bug-free, I started to test it on Mobile Safari and then I moved all my code inside a simple XCode project (thank you @mattmight) with a webView which loads an HTML file. However, inside the webView, the transitions’ performance got worse and the elements started flickering.

In order to look into the problem, I started removing CSS proprieties and I discovered that some of them can drastically affect the transitions’ performance.

Some of the proprieties which I have tested and can cause performance issues are:
-webkit-backface-visibility: hidden;
-webkit-perspective: 800;
-webkit-transform-style: preserve-3d;
-webkit-transform: translate3d(0,0,0) rotate(0) scale(1);

CSS animation benchmark test

I set up a simple HTML file which records the Javascript performance during the transitions. Unfortunately, I could not benchmark the CSS because the transitions are hardware accelerated and Mobile Safari’s JS engine is not fast enough to track the numbers’ position.

In these tests, I set a -webkit-transition: all 4s linear 1s propriety to a long column of text moving it from top: 0 to top: -2000px.

Then, with a simple Javascript interval of 50ms, I recorded how many times the interval function has been called. Obviously this function slowed down the performance, but the page was really raw, so I thought it could reflect the same performance as a page with some chrome.

I chose to run five tests on four different environments and I repeated each test three times on every environment.

The five tests are sequential and on each step I added a new CSS propriety through Javascript.

  • Style 1: neat CSS animation with no -webkit-* proprieties except the linear transition.
  • Style 2: add-webkit-backface-visibility: hidden to all moving elements
  • Style 3: add -webkit-perspective: 800 to the body
  • Style 4: add -webkit-transform-style: preserve-3d to the body
  • Style 5: add -webkit-transform: translate3d(0,0,0) rotate (0) scale (1) to all moving elements

The four environments are: - Mobile Safari on iPhone 4, iOS 4.3 - Compiled app (webView) on iPhone 4, iOS 4.3 - Mobile Safari on iPhone 3G, iOS 4.2 - Compiled app (webView) on iPhone 3G, iOS 4.2

I chose these two different platforms to empathize the performance’s gaps between them.

Results of animating one element

iOS performance while animating one element

The graph above shows you the results of the animation of one element. As you can see, on the iPhone 3G the performance goes down every time I added a propriety to the element. Though, the situation is OK on iPhone 4, where Webkit handles better the multiple -webkit-* proprieties.

Although on iPhone 3G the best Javascript performances, ~16 fps, are with the “neat style”, on the iPhone 4 there are the highest fps, about 18, with the propriety -webkit-backface-visibility: hidden.

Nevertheless, I have to do a consideration: despite the recorded values, by adding any CSS proprieties the transition becomes less smoother, even if the fps (so Javascript performances) are higher. For instance, on iPhone 4 with Style 5 the collected fps are higher than with Style 1, but the animation flickers.

Maybe, while adding these proprieties, the CPU works less (so the Javascript performances are better), but the GPU is still limited on the devices so the animation is smoother with less -webkit-* proprieties. Unfortunately, I cannot prove this hypothesis, but the slowdown is clearly visible.

Results of animating two elements simultaneously

iOS performance while animating two elements

In the tests with two elements animated simultaneously, the iPhone 4 has quite good performances, but on iPhone 3 the more -webkit-* proprieties you add, the more the Javascript recording interval becomes less frequent. Moreover, there is a difference of 20% between performances on Mobile Safari and webView with the “neat style”.

As I have already said, I am not able to record the real CSS performances, but I can say that while doing the tests I could clearly see that the transitions ran slower and less smoother on every environment depending on how many -webkit-* proprieties I added.

In particular, on the iPhone 3G the CSS transitions smoothness reflect the Javascript performances: so that on Style 5 the numbers’ animation is really slow, if not almost stop.

Comparison of the previews’ graphs

iOS CSS performance comparison

This comparison graph shows how iPhone 4 splits the resources between CPU and GPU. Javascript performances remain quite the same on every test, even if CSS transition becomes less smooth.

However, the iPhone 3G does not manage to load as well as the latest iPhone. In particular, the animation of multiple elements inside a webView becomes 60% slower than the single animation.

Last thoughts

Thanks to these tests I have demonstrated that there are some custom Wekit CSS proprieties which strongly influence the performance of Javascript and of the animation itself, even if these proprieties do not add any visual effect on the page.

Obviously, some of these proprieties are required in certain circumstances, but I recommend you to add these proprieties only if you really need them. Otherwise, leave the -webkit-* as default, so performances are not penalized.

Furthermore, I have recorded such values by animating a “big” element for a long period of time. If you only need small animations, such as apps transitions, you will not notice any difference.

If you want to do your own tests, I have released the source of the HTML page for Safari Mobile and the XCode Project for webView tests.

We can inspect more in depth CSS animations’ performances by testing other types of transitions or the keyframe animations. This is not the only way to test iOS performances and my tests can be improved in many aspects. So, if you have a good idea on how to track CSS animations’ frame rate, please leave a comment!

If I will have enough time to do that, I will try to use CSS animations instead of CSS transitions. I think that both CSS transitions and CSS animations are hardware accelerated, but maybe the way iOS treats them is different.

 Do you want to see a real app?

I have developed a small app called Lottery Roulette which is completely built with HTML and CSS technologies. My app also uses CSS transitions to simulate the numbers’ rotation as a slot machine does.

If you want to test it directly on your device, this is the App Store link.