In this article I am going to introduce you to jQuery Mobile, hereafter fondly referred to as jQM. We will step through the absolute minimum required to author a website with jQM, touch on some of the preliminary pitfalls, and build up a reference project with which you can hold hands as you take your own first steps.

jQuery Mobile refers to herself as a “touch-optimised web framework for smartphones and tablets”, and further, as “a unified user interface system across all popular mobile device platforms, build on the rock-solid jQuery and jQuery UI foundation”. Essentially, then, author your document using this framework and practically guarantee a good outcome on current mobile devices.

Set Up

Wherein we set up a local development environment for our first experiments. Download jQM, and I would advise that you also download a copy of jQuery, upon which jQM is dependent, to use locally, whether or not you end up using hosted versions in production. Move all of the downloaded files into your project.

I chose to house all of these files in a /jqm/ folder, within the root directory of my project. This is in order to preserve the links between the scripts, CSS and sprite images of the jQM framework. You may choose more traditional /js/ and /css/ and /img/ folders, but maintenance will be required. Bear in mind the fluid nature of the jQM project, and its current alpha state.

Basics

Create your root index.html file, or equivalent. Then if you head over to jQM’s docs and demos, navigate through components, pages & dialogs, to the section explaining the basic anatomy of a page, you will find her boilerplate templates. To get up to speed quickly, copy and paste in a complete single page template, then switch out the for the multi-page snippet.

I have updated the links in the of the document to point to my /jqm/ folder. At this early stage in it’s life, there are a few wrinkles in the boilerplate code, such as comments after the <footer> containers, but they can be forgiven. A few minor tweaks, and I present my own revision of the boilerplate template code.

<!DOCTYPE html> 
<html> 
    <head> 
        <title>Page Title</title> 
        <link rel="stylesheet" href="jqm/jquery.mobile-1.0a4.1.min.css" />
        <script src="jqm/jquery-1.5.2.min.js"></script>
        <script src="jqm/jquery.mobile-1.0a4.1.min.js"></script>
    </head> 
    <body> 
        <!-- Start of first page -->
        <div data-role="page" id="foo">
            <div data-role="header">
                <h1>Foo</h1>
            </div><!-- /header -->
            <div data-role="content">   
                <p>Hi, I'm Foo.</p> 
                <p>I'm first in the source order so I'm shown as the first page.</p>        
                <p>View the internal page called <a href="#bar">Bar</a></p> 
            </div><!-- /content -->
            <div data-role="footer">
                <h4>Page Footer</h4>
            </div><!-- /footer -->
        </div><!-- /page -->
        <!-- Start of second page -->
        <div data-role="page" id="bar">
            <div data-role="header">
                <h1>Bar</h1>
            </div><!-- /header -->
            <div data-role="content">   
                <p>Hello, I'm Bar.</p>  
                <p>I'm second in the source order, and I'm an internal page.</p>        
                <p><a href="#foo">Back to Foo</a></p>   
            </div><!-- /content -->
            <div data-role="footer">
                <h4>Page Footer</h4>
            </div><!-- /footer -->
        </div><!-- /page -->
    </body>
</html>

The documentation of basic page anatomy explains that you can happily link to external pages, and equally happily contain internal pages in the same document. Your choice will be based on common sense factors depending on the site or app you are building, but our reference project will, for simplicity’s sake, house all of its pages internally. We will return to the intricacies later.

For now, note the important structural elements. Each element containing a page includes data-role="page" in the same way that a class="" is added to an element. Each of the pages contains three more elements, one each of a data-role="header" and a data-role="content" and a data-role="footer". This use of data-role="" is how jQM rolls.

Fire up your project right now, with this code in place, to observe the effect of the simple HTML structure with the associated jQM data-role attributes. You should have two linked ‘pages’, slide transitions included for free. For the precocious, try adding additional documents and relevant links, to observe how externals links also ‘just work’ without any special configuration.

Here is the first pro-tip. Add a data-title="" attribute to each data-role="page" container, which will mimic the traditional <title> found in the of an HTML document. Whilst jQM does a fine job of auto-updating page titles for Ajax navigation, on multi-page sites you can add this attribute to manually define the titles, and in so doing help the history stack.

Context

Our reference project is concerned with illuminating how to create various shapes using CSS alone, and zero images. What better context, given our responsible aim to limit the downloads for bandwidth constrained mobile devices, coupled with the opportunity that mobile browsers and their advanced support of CSS3 presents.

The lion’s share of credit for this fancy CSS work goes to Chris Coyier and his Shapes of CSS, and the remainder to his adoring and talented public, for their conversation around and contribution to CSS3 only shapes. Importantly, note that the final version of our reference site does not display all possible shapes, so it is essential you follow the above links and see, first hand, for yourself.

So, in order to illuminate CSS shapes, we will change the boilerplate code so that the first page displays an example of a CSS shape, and the second page displays the CSS required to create that shape out of a single HTML element. But first a diversion into HTML5. The documentation states that a jQM site must start with an HTML5 doctype to take full advantage of the framework.

HTML5

For an in depth guide to HTML5, look no further than HTML5 & CSS3 For the Real World. As I build out our reference site, I will sprinkle in some new HTML5 elements and remove some of the old cruft. Bonus points for calling out, in the comments, where I deviate from the doctrine advocated in the aforementioned book.

  • Change all <div data-role="page"> elements to <section data-role="page">
  • Change all <div data-role="header"> elements to <header data-role="header">
  • Change all <div data-role="content"> elements to <article data-role="content">
  • Change all <div data-role="footer"> elements to <footer data-role="footer">

Let’s ditch the <!-- /header --> type comments, we don’t need them because the markup speaks for itself. We can safely remove type="text/javascript" from script links and type="text/css" from stylesheet links. Sprinkle in a tag, first in the <head>. Finally, note my simple good manners in adhering to unambiguous XHTML style closing slashes.

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8" />
        <title>CSS3 Shapes</title> 
        <link rel="stylesheet" href="jqm/jquery.mobile-1.0a4.1.min.css" />
        <script src="jqm/jquery-1.5.2.min.js"></script>
        <script src="jqm/jquery.mobile-1.0a4.1.min.js"></script>
    </head>
    <body>
        <section data-role="page" id="infinity" data-title="Infinity">
            <header data-role="header">
                <h1>Infinity</h1>
            </header>
            <article data-role="content">
                <div class="infinity"></div>
                <style>
                    .infinity {
                        position: relative;
                        width: 212px;
                        height: 100px;
                    }

                    .infinity:before,
                    .infinity:after {
                        content: "";
                        position: absolute;
                        top: 0;
                        left: 0;
                        width: 60px;
                        height: 60px;    
                        border: 20px solid #fc2e5a;
                        -moz-border-radius: 50px 50px 0 50px;
                             border-radius: 50px 50px 0 50px;
                        -webkit-transform: rotate(-45deg);
                           -moz-transform: rotate(-45deg);
                            -ms-transform: rotate(-45deg);
                             -o-transform: rotate(-45deg);
                                transform: rotate(-45deg);
                    }

                    .infinity:after {
                        left: auto;
                        right: 0;
                        -moz-border-radius: 50px 50px 50px 0;
                             border-radius: 50px 50px 50px 0;
                        -webkit-transform:rotate(45deg);
                           -moz-transform:rotate(45deg);
                            -ms-transform:rotate(45deg);
                             -o-transform:rotate(45deg);
                                transform:rotate(45deg);
                    }
                </style>
                <p><a href="#infinity_css" data-transition="pop">Infinity CSS</a></p>
            </article>
            <footer data-role="footer">
                <h4>BuildMobile: jQuery Mobile</h4>
            </footer>
        </section><section data-role="page" id="infinity_css" data-title="Infinity">
            <header data-role="header">
                <h1>Infinity</h1>
            </header>
            <article data-role="content">   
                <pre>
                    <code>
.infinity {
    position: relative;
    width: 212px;
    height: 100px;
}

.infinity:before,
.infinity:after {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    width: 60px;
    height: 60px;    
    border: 20px solid #fc2e5a;
    -moz-border-radius: 50px 50px 0 50px;
         border-radius: 50px 50px 0 50px;
    -webkit-transform: rotate(-45deg);
       -moz-transform: rotate(-45deg);
        -ms-transform: rotate(-45deg);
         -o-transform: rotate(-45deg);
            transform: rotate(-45deg);
}

.infinity:after {
    left: auto;
    right: 0;
    -moz-border-radius: 50px 50px 50px 0;
         border-radius: 50px 50px 50px 0;
    -webkit-transform:rotate(45deg);
       -moz-transform:rotate(45deg);
        -ms-transform:rotate(45deg);
         -o-transform:rotate(45deg);
            transform:rotate(45deg);
}
                    </code>
                </pre>
                <p><a href="#infinity" data-transition="pop" data-direction="reverse">Infinity Shape</a></p>
            </article>
            <footer data-role="footer">
                <h4>BuildMobile: jQuery Mobile</h4>
            </footer>
        </section>
    </body>
</html>

Transition & Direction

Digging in deeper, note the addition of a data-transition="pop" attribute to the text based links. Add a data-transition attribute to a link to change the default transition from slide, to any of the supported choices including slideup, slidedown, pop, fade and flip. Due to the use of CSS transforms, the animations should be hardware accelerated on many mobile devices.

jQM politely attributes the code for the transitions to jQT, or jQTouch, with some small modifications. jQT was built by David Kaneda and is maintained by Jonathan Stark, and there is no doubt we will publish an introduction to the jQT library here at BuildMobile in the near future, because it offers notable and interesting differences.

Also note the addition of data-direction="reverse" to the link from the second page back to the first. This forces a backwards transition such that the data-transition="pop" shrinks rather than grows. But make careful note that data-direction="reverse" specifies a reverse transition without actually going back in history.

Now is a good time to contemplate the flow pf pages, internal or otherwise, and choose appropriate transitions and directions. There is some advanced documentation on redirects and linking to directories, that we might cover in a later tutorial. Of course, you can read more about the technical details of the navigation model, Ajax, hashes and history in the docs.

Basic List Views

Our reference site contains more than a handful of shapes, so we will add a list for navigation. Add a new container with a data-role="page" and make sure it is the first in the source code. Inside the data-role="content" container, add a <ul> and an <li> for each of our shapes. Because our pages are internal, each <li> should contain an id based href="#shape".

The simple addition of data-role="listview" to the <ul> delivers the jQM magic. The list will be transformed into a full width element, displaying the anchor text to the left and the standard right-arrow icon. Clicking, or tapping any of the links, will trigger the standard right-to-left slide animation into the linked page.

Adding some juice to the list is just as simple. Add data-filter="true" to the <ul> for an instant client side search. Optionally add data-filter-placeholder="" and your chosen placeholder text. The documentation for lists is expansive, but you will find advanced functionality is simple to achieve, and follows the same patterns as we have covered thus far.

Notes on Navigation

Our reference site has a navigation page, nine ‘shape’ pages, each of which has a ‘CSS’ page. All bar the first has a ‘back’ button added automatically by the jQM framework, which comes as standard with the data-role="header". But without intervention, it is flawed and breaks the mental model.

If you were to toggle between the ‘shape’ and the ‘CSS’ page several times, each transition would be added to the history stack. Clicking the ‘back’ button would reverse that history and toggle between the ‘shape’ and ‘CSS’ pages as many times, before finally going back the the navigation page where you started.

So we add data-rel="back" to the link, which mimics the back button, going back one history item and ignoring the anchor’s default href. Despite being ignored, it is important to add a meaningful href that actually points to the URL of the referring page, so that C-grade browsers can follow it, and the flow doesn’t break.

I predict this will change, we may not even get the ‘back’ button by default in future. Again I point you back to the documentation on the navigation model. For now, be aware that a link from an Ajax loaded page into multiple internal pages requires the addition of rel="external" or data-ajax="false" to do a full reload clearing the Ajax hash in the URL.

Closing

Not a single line of CSS was written in the making of the ‘Shapes’ reference site, besides the CSS in the content of course, which I am discounting. Zero images were required, besides the existent sprites in the jQM framework. The total weight of the jQM framework, and the jQuery library on which it depends, is approximately 234KB plus just 20KB for our reference document.

Time has almost run out, and in this article we have merely scratched the surface in touching on just some of the documentation of pages and dialogs, toolbars and list views. The documentation is easy to follow on your own, but you might want to request additional coverage of buttons, forms, and general content formatting, in the comments.

In a future article I will dive deeper, wherein the various aspects of the API are covered. But for now, let’s do some crowd sourced guerilla testing. Fire up the reference site on your mobile, be that an Android phone, and iPhone or an iPad, and tell the world what is and is not working. I will try and address the points raised in the next instalment.

Extra Credits

Make a site behave more like an app with the inclusion of a in the of the document. This only works when the site is added to the home screen. The old skool method was to remove the chrome with the addition of onload="setTimeout(function() { window.scrollTo(0, 1) }, 100); to the tag.

Better still, add to the for non retina smartphones, and drop the PNG into the root directory. Then add to the and the PNG in the root for a retina display.

Sponsors