Implementation: UI: Comparing software and hardware-accelerated transitions on mobile
This article was originally published on CodePen on September 24th, 2015.
One thing you’ll hear when speaking of your web project on mobile, including is that you won’t be able to achieve the same smoothness as a native app. That may be true or not, depending on two factors: the way you implement transitions, and if the efficient way is available on your target devices.
To check the difference, just have a look at the sample below:
If the two animations look the same, you’re either running it on a desktop/laptop machine or a very good mobile device. But as the time of this writing, most mobile devices will show a difference.
The “naive” way
Don’t be offended by the term, because you have a reason for believing that way should work: it works really good on your desktop. Actually, it also runs pretty smoothly on the latest mobile devices. But it doesn’t on older mobile devices.
That difference is the one between software and hardware-accelerated (HA) animations. And, you understand it, your goal is to achieve the latter.
In the example above, however, as in most web transitions, the animation is not requiring any 3D transformation. The “naive” way to describe it was:
.scrolled {
transition: left 1s ease;
left: 0;
&.ng-enter { // AngularJS 1.3 transition class
left: 100%;
}
&.ng-enter-active { // AngularJS 1.3 transition class
left: 0;
}
&.ng-leave { // AngularJS 1.3 transition class
left: 0;
}
&.ng-leave-active { // AngularJS 1.3 transition class
left: -100%;
}
}
But none of this is guaranted to be delegated to a GPU, if any. Most likely, the transition of the left
property will be handled by the main CPU. Depending of the power of it, this may slow down both your animation and any parallel work.
The efficient way
Leading the browser to use HA can be achieved in multiple ways. More generally, it consists of requiring operations that are too CPU consuming, so the device will ask another processor to handle it in parallel. It also consists in hoping that you do access have such another processor, as we’ll see.
For graphical operations, that “other” processor is the Graphical Processor Unit, or GPU. Typically, when 3D graphics are required, the workload can be delegated to the GPU, which will handle it much faster, thanks to the parallelism, but also thanks to its specialized built-in 3D routines.
In order to trigger GPU handling, you have to act if you’re aiming a 3D transformation:
.scrolled {
transition: transform 1s ease;
transform: translate3d(0, 0, 0);
&.ng-enter {
transform: translate3d(100%, 0, 0);
}
&.ng-enter-active {
transform: translate3d(0, 0, 0);
}
&.ng-leave {
transform: translate3d(0, 0, 0);
}
&.ng-leave-active {
transform: translate3d(-100%, 0, 0);
}
}
No real 3D here — only the x coordinate is modified — but the GPU will take care of the computation, for the sake of smoothness.
Is that simple?
The next thing to do then, is to test it on your target device(s). Not only in a browser, but in a WebView if you intend to deliver web inside a native wrapper (such as PhoneGap). This because:
- No all devices have HA. Notably, any Android device before 4.4.3 won’t have it.
- An animation can run smoothly on a mobile browser, but may not in a WebView of a native shell (such as PhoneGap) depending on the device/OS. So, even when testing on target devices, you should never check animation smoothness in an “ideal” case, but against concurrent, time-consuming work such as an XHR request (see how to handle such a case in “AngularJS page transitions and loading techniques”).