Lately, we’ve been exploring ways to offer web apps that perform like native apps on mobile devices. For this short sprint we targeted mobile WebKit browsers—especially the default browsers on iOS and Android—because of their widespread use and excellent support for HTML5 and CSS3.
Here are a few things we’ve learned along the way:
Targeting WebKit browsers specifically lets us make liberal use of
-webkit extensions to CSS3 (as seen in the spinner animation we shared recently). Incompatibilities between the current browsers on iOS and Android devices has not been an issue so far.
The biggest difference is the default installed fonts. We prefer Lucida Grande for our apps in desktop browsers, but the font isn’t available on any of the mobile devices we tried. iOS offers Verdana, Helvetica or Arial; Android devices have Droid Sans. Just like on the desktop, Verdana is large relative to other fonts. For that reason, we choose Helvetica on iPhone. Compared to Helvetica, Droid Sans appears a bit smaller and more condensed.
Form widgets are another distinct difference between the platforms, but because of the flexibility of WebKit are less of an issue. The native browser widgets on Android are ugly in some cases and unuseable in others.
For example the checkbox widget has a checkmark in both the checked and un-checked states—the checkmark turns green when “checked”. Using CSS we were able to create new widgets that look nearly identical on both platforms. Because of the differences in font rendering, however, it can be difficult to do things like align text inside a button. Web designers should not be surprised by this since it’s a common hassle between even desktop browsers and platforms.
Default form inputs on iOS (left) and Android. Notice how the label on the submit button is positioned differently on each. Or imagine a long list of Android checkboxes where none is “checked”. Are they all checked or un-checked?
For the purposes of testing your app, both platforms offer desktop simulators. Testing on the iPhone SDK simulator is fast, convenient, and fairly representative of using the actual device—it actually looks like an iPhone.
The iPhone simulator supports the iPad, iPhone and iPhone 4 devices, but only on the latest OS version. Because of this, supporting older versions of Mobile Safari could be a challenge. While it’s possible to run multiple versions of the iPhone SDK, testing on older versions is best done on a physical device.
The Android SDK’s simulator, however, is a sluggish java app launched from the command line that gives no sense of the feel of the OS within the context of the hardware. It does account for the wide array of Android hardware and software versions/features in the wild, but in an obtuse way. You can’t, for example, launch an HTC Droid X profile but instead have to spin up a new virtual device and enter the hardware profile yourself.
In fact, all testing is best done on real hardware. The simulators give a poor sense of the app on the actual devices. This is especially true in terms of scale. The much smaller pixel size on desktop computers means the simulated devices appear much larger than you’d expect on your computer screen. Much larger than the actual device. Type that looks great on the device can look horsey on the desktop.
For this reason we’ve also been testing on real phones. Using Dnsmasq we can serve requests for the app on our development machines to devices via a wifi network. Touching the UI is an important distinction from the desktop simulator. Real devices are also particularly useful for previewing on the iPhone 4’s retina display. And a real Nexus One is much faster than the simulated Adroid device.
The iPhone’s retina display also revealed some additional challenges. Web pages in Mobile Safari on iPhone 4 are scaled at twice the resolution of the earlier iPhone models. This means that images created at 72dpi look fuzzy on iPhone 4 where they are zoomed to twice their size.
-webkit browser extensions to CSS handle this scenario well. Images in CSS targeted at Mobile Safari should be designed at exactly twice the intended display size. So a 16px x 16px icon rendered as a CSS background image should be built in Photoshop at 32px x 32px. Then, we can tell the browser the intended display size using the
-webkit-background-size property like this:
background: url(images/icon_retina.png) no-repeat; -webkit-background-size: 16px 16px;
That displays a high resolution image for iPhone 4 when it doubles the dimensions, and a shrunken version for the lower resolution devices. This appears to work similarly on Android though we haven’t tested a wide range of resolutions. We’ve used the convention of naming images that require this special handling with “_retina” in the file name.
Web app settings
We also explored the
apple-mobile-web-app-capable settings which lets apps that are bookmarked to the home screen on iOS act more like native apps. These settings let you specify a loading screen image, allow for local caching of data (even the entire app), and hide the browser chrome. Unfortunately nothing like this yet exists on the Android platform, but it’s a great step for browser-based apps so hopefully the idea will catch on.
Despite opinions to the contrary, mobile web apps still feel like an excellent opportunity to offer native-like performance without having to specialize in a particular platform, or be subject to the whims of an overlord.
Browser-based mobile apps clearly have the potential to offer user experience that is on-par with native apps. Of course designing that kind of experience is going to require more than emerging mark-up and style techniques—it’s not going to be enough to just serve a mobile stylesheet for your app. Offering a native-worthy mobile experience requires you to rethink the UI of your app and deliver it within an environment where touch is the rule. A big part of this exploration not covered here considered fast page rendering, touch interaction, and local asset storage. We hope to share some of the tech side in another post.