Qpsoftware blog feed

Web app Iphone HTML5 offline

Developing an application for the iPhone requires knowledge in Objective-C programming language, which is a new language to learn, with a complicated structure.

We might have tried reading tutorials about developing for the iPhone, but it's C—or a form of it—and it’s really hard to learn. You also need to pay a special license to Apple. Then when you finally finish programming, you have to ask Apple for permission to put the app in the Apple store, which they may or may not grant. And what about other mobile OS? The application developed will not run on Androïd nor on the Blackberry mobile.

We have more and more clients asking us to develop web applications to promote their brand, so we found the best solution to propose to them.

The solution is an HTML5 web application which will run in all the new smart phones that have HTML5-capable browsers.

We can create a native app that lives with all the other apps, and for the most part, it’s going to be a pitch-perfect imitation.

We can do this with the skills that we already have: HTML(5), CSS, and JavaScript.

In this article, I’ll show you how to create an offline HTML5 iPhone application. More specifically, I’ll walk you through the process of building a Tetris game. I optimize this version for iPhones only but after few updates I could also run it on the Androïd system.



What am I talking about when I say "offline"? Well, it means that we have a custom icon, a custom startup screen, a native look-and-feel, and you can use the app even when the phone isn’t connected to the Internet.

The app should be as functional as it can when it is offline, just like normal native mobile apps.

This is a tutorial specifically for iPhones but most of these techniques apply to all phones that have HTML5-capable browsers.

Yeah, I mean it, check out the following image. It has no URL bar and no navigation at the bottom. It looks just like a native mobile application. You can observe that we are in airplane mode so the application is working offline.

Iphone html5 web app offline


You are going to need access to a server where you can change the HTTP Headers on your files. This is because we need to take advantage of HTML5′s offline caching (more on this later down the page).

Apache does this really well and you can just add something to a .htaccess file and it will just work. Here’s a tutorial on modifying HTTP headers using htaccess.

The other thing you need to do is to enable the debug bar in Safari’s web browser on your iPhone unit. Go to the > Safari > Developer on your iPhone, then turn on the debug console. This will help you spot potential JavaScript errors.

Once you’ve built your app, you should turn this off so that you will get the full experience when testing your HTML5 iPhone app.

debug iphone console

About the App

Icon and Startup Screen

The icon needs to be 57px x 57px.

The iPhone will round the corners of your icon, create a dropshadow, and add a shine to whatever icon you use.

It should be in PNG or JPG format.

Here is what I used for the tetris game.

Icon and Startup Screen

The startup screen needs to be 320px x 460px and should also be in PNG or JPG format.

Here is what I used for the startup screen.

Icon and Startup Screen

Some tips before you start

Stay small, sparse and simple.

  • Small: This is mobile app development so even though you are caching your stuff, it’s still a smart idea to keep your file sizes lean.
  • Sparse: You should try to keep the amount of files you deal with as low as possible.
  • Simple: Start with a few simple ideas and execute it. By keeping your scope small, you can get things done faster.

Application Cache

This is a new standard, you can read the spec here.

Application caching allows browsers to determine in advance all the files a web page will need for the web page to work.

It will cache those files (to a fault, sometimes). The syntax of this file is simple: just list the locations of your files in either absolute (e.g. or relative to the manifest file (/picture.png). The browser will keep those files offline.

You can also list a few URLs that should not be cached, but this isn’t pertinent for our offline app (if you’re interested, read about this in the documentation).

One tricky part to this whole thing is that the manifest (the list of files that need to be cached offline) has to be passed with a filetype Header set to text/manifest. That is why you need access to a web server that can set HTTP headers.

Screen Size

A quick note when designing your application: When you are in app mode, you have a screen size of 320px x 460px. When you are in web mode, it has a screen size of 320px x 356px. This can affect the user interface of your offline HTML5 app.

Here you can see the difference side by side.

Screen Size iphone web app


It’s a real browser so your HTML is exactly the same. The iPhone browser is also in the forefront of HTML5, so dig into the spec.

For more in-depth detail, check out the Safari Developer’s corner:

Let’s get coding

The app starts by defining your markup. here is the markup for my Tetris app.

<!DOCTYPE html>
<html manifest="tetris.manifest">

    <meta name="viewport" content="user-scalable=no, width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
    <meta name="apple-mobile-web-app-capable" content="yes" />

    <meta name="apple-mobile-web-app-status-bar-style" content="black" />
    <link rel="apple-touch-icon" href="iphon_tetris_icon.png"/>

    <link rel="apple-touch-startup-image" href="startup.png" />
    <link rel="stylesheet" href="tetris.css" type="text/css" media="screen, mobile" title="main" charset="utf-8">

    <title>offline Tetris</title>
   <!-- Put your Markup Here -->
   <script type="text/javascript" src="tetris.js"></script>


First, notice the Doctype. Isn’t HTML5 awesome?

The manifest="cache.manifest" property on the <html> tag is how the browser knows that we want to cache this web page offline.

There’s proprietary Apple markup on our HTML5 page. A brief explanation of each:

  • apple-mobile-web-app-capable: This is another tip-off that we want to be an offline app.
  • apple-mobile-web-app-status-bar-style: This hides the status bar, and nav bar when the app is offline.
  • apple-touch-icon:This is the pointer to the image that want to be the icon.
  • apple-touch-startup-image: This is a url pointing to the startup image.

Also note that you should put CSS at the top and JavaScript at the bottom (best practices still apply here).


It’s almost the same as a normal web page. There are some specific -webkit CSS rules that you can use that do some really cool things like animation, but this is a quick-and-dirty guide and that’s outside of the scope of this article.

The CSS is just Plain Jane.

body {
    background: #d7d7d7;
#tetris {
    width: 320px;
    height: 460px;

The style is really just to the div element on our web page to make sure it fits in the iPhone’s viewport properly.


The JS was written originally for a normal web browser. The only modifications I had to make was to support not having a keyboard.

In general, JS functions work just fine on the iPhone—there are exceptions though. Think about something like a mouseover, the event exists on the iPhone, but I am not sure how helpful it is when you don’t have a standard pointing device (such as a mouse).

When you have all of that, you can test it out but opening your index.html in an iPhone, and you should be able to see everything work.

Then, next step is to server it from an actual webserver that can set the proper settings on the cache.manifest.

Then you could be able to add it to the home screen and have all the extras, and see the offline mode.

You can see a working version I have set up at:

Bonus Section: Offline Data

Along with the ability to keep files that are needed offline, you can also store user data in an offline database. There are two major APIs for per user and/or per page data. The first is localStorage. localStorage, is an easy to use key-value store with a dead simple API.

localStorage.dataToStore = 5;
console.log(localStorage.dataToStore); // 5

You can use this for storing the user’s score, for example.

The second is actually an offline SQL engine, a webdatabase. The APIs are a little more advanced. Here is a little of you will see.

// Try and get a database object
var db;

try {
    if (window.openDatabase) {
        db = openDatabase("NoteTest", "1.0", "HTML5 Database API example", 200000);
        if (!db)
            alert("Failed to open the database on disk.  This is probably because the version was /
            bad or there is not enough space left in this domain's quota");
    } else
        alert("Couldn't open the database.  Please try with a WebKit nightly with this feature enabled");
} catch(err) { }

// Check and see if you need to initalize the DB
db.transaction(function(tx) {
    tx.executeSql("SELECT COUNT(*) FROM WebkitStickyNotes", [], function(result) {
    }, function(tx, error) {
        tx.executeSql("CREATE TABLE WebKitStickyNotes (id REAL UNIQUE, note TEXT, timestamp /
        REAL, left TEXT, top TEXT, zindex REAL)", [], function(result) {

// Insert a test Note.
var note = {
    id: "1",
    text:" This is a test note",
    timestamp: "112123000",
db.transaction(function (tx)
    tx.executeSql("INSERT INTO WebKitStickyNotes (id, note, timestamp, left, top, zindex) VALUES /
    (?, ?, ?, ?, ?, ?)", [, note.text, note.timestamp, note.left,, note.zIndex]);

// Get all the notes out of the database.
db.transaction(function(tx) {
    tx.executeSql("SELECT id, note, timestamp, left, top, zindex /
    FROM WebKitStickyNotes", [], function(tx, result) {
        for (var i = 0; i < result.rows.length; ++i) {
            var row = result.rows.item(i);
            var note = new Note();
   = row['id'];
            note.text = row['note'];
            note.timestamp = row['timestamp'];
            note.left = row['left'];
   = row['top'];
            note.zIndex = row['zindex'];

            if (row['id'] > highestId)
                highestId = row['id'];
            if (row['zindex'] > highestZ)
                highestZ = row['zindex'];

        if (!result.rows.length)
    }, function(tx, error) {
        alert('Failed to retrieve notes from database - ' + error.message);

Wrap Up

There is lot that can be done with offline HTML apps. Games, like tetris, are even possible, but you would probably want to consider what you want to do and make sure its right for an offline app. Quake 3 Arena, probably not. A to-do list app, definitely.

Let thousands apps bloom!


Related Content


Posted by: admin