Here at Quick Left, we often use Cordova with Backbone.js to build mobile applications for both Android and iOS. This setup takes advantage of the best of both worlds — we get native device functionality through Cordova and the ease of creating complex, interactive websites with Backbone.
This makes it easy to develop quickly, but also makes it easy to overlook limitations of mobile browsers and processors and develop with the modern desktop browser in mind. This can lead to the app working perfectly fine when developing on your desktop browser, but then exhibit significant rendering problems, (e.g., flickering) when testing on devices. In addition, the problems might differ from device to device. We found that native browsers on different mobile operating systems respond differently to content-rich DOMs.
1. Keep It Clean (the DOM, that is)
Our application loads a variable amount of content depending on the item a user chooses to view. It could be just a few bullet points of text, or multiple paragraphs with images or videos. We found that only the most content-heavy pages caused rendering issues. The first step we took was to look critically at our HTML structure. Do we really need this
<div> inside of that
We explored replacing our
<li><a></a></li> with just
2. Less is Better
A second option we explored was to reduce the amount of content being loaded at one time. For example, on list-views, we load 10 at a time and stop when the device screen is full. Rather than load potentially hundreds of list items, we're loading 10 or 20, and only loading more when the user scrolls down.
3. Beware the Box-Shadow
While box-shadows and other cool CSS3 effects are fun to implement, some of them are a bit too much for mobile browsers to handle. Box-shadows, it turns out, can really slow down your rendering speeds. For our application, we were able to use box-shadows on newer iOS devices, but had to remove them for Android devices.
4. Different Strokes for Different… Devices
Finally, if you're still experiencing rendering problems, it's time to try some CSS 'hacks'. We found that no single hack seems to do the trick for every OS, and even different versions may respond differently (or not at all!). These are some that worked for us:
iOS and Android:
The null-transform hack! What does it do, you ask? On the surface, it appears that we are using CSS to move an element by 0x, 0y, and 0z — so no movement at all! And that's true — we're not trying to move the element. We just want it to render more smoothly. The real reason we do this is that it forces rendering to be handled by the device's GPU instead of relying on the browser. This drastically improved our rendering on the content-heavy pages of our application for both iOS and Android. Since you don't want your app to hog your user's device GPU, apply this only to the elements that really need the extra rendering power.
On the Android devices we tested, we found that the null-transform trick helped but didn't completely alleviate the problem. Fortunately, adding this trick fixed things:
Essentially, this CSS prevents the backside of the element from being rendered when rotated 3-dimensionally.
The above resolved rendering problems on our Android 4x devices, but caused significant new issues on Android 2.3. Rendering on Android 2.3 did not have the initial problems, so we limited the application of the above fixes to not include Android 2x (using classes placed on the DOM based on device type).
By using a combination of these strategies we were able to build a solution that worked smoothly for all of our target devices without sacrificing performance or design.