The page is the primary unit of interaction in jQuery Mobile and is used to group content into logical views that can be animated in and out of view with page transitions. A HTML document may start with a single "page" and the AJAX navigation system will load additional pages on demand into the DOM as users navigate around. Alternatively, a HTML document can be built with multiple "pages" inside it and the framework will transition between these local views with no need to request content from the server.
A jQuery Mobile site must start with an HTML5 doctype
to take full advantage of all of the framework's features. (Older devices with browsers that don't understand HTML5 will safely ignore the 'doctype' and various custom attributes.)
In the head
, references to jQuery, jQuery Mobile and the mobile theme CSS are all required to start things off. jQuery Mobile 1.3.2 works with versions of jQuery core from 1.7.0 to 1.9.1. The easiest way to get started is to link to files hosted on the jQuery CDN or for best performance, build a custom bundle:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
...content goes here...
</body>
</html>
Note above that there is a meta viewport
tag in the head
to specify how the browser should display the page zoom level and dimensions. If this isn't set, many mobile browsers will use a "virtual" page width around 900 pixels to make it work well with existing desktop sites but the screens may look zoomed out and too wide. By setting the viewport attributes to content="width=device-width, initial-scale=1"
, the width will be set to the pixel width of the device screen.
<meta name="viewport" content="width=device-width, initial-scale=1">
These settings do not disable the user's ability to zoom the pages, which is nice from an accessibility perspective. There is a minor issue in iOS that doesn't properly set the width when changing orientations with these viewport settings, but this will hopefully be fixed in a future release. You can set other viewport values to disable zooming if required since this is part of your page content, not the library.
Inside the <body>
tag, each view or "page" on the mobile device is identified with an element (usually a div
) with the data-role="page"
attribute.
<div data-role="page">
...
</div>
Within the "page" container, any valid HTML markup can be used, but for typical pages in jQuery Mobile, the immediate children of a "page" are divs with data-roles of "header"
, "content"
, and "footer"
.
<div data-role="page">
<div data-role="header">...</div>
<div data-role="content">...</div>
<div data-role="footer">...</div>
</div>
Putting it all together, this is the standard boilerplate page template you should start with on a project:
<!DOCTYPE html>
<html>
<head>
<title>Page Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" />
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
<div data-role="page">
<div data-role="header">
<h1>Page Title</h1>
</div><!-- /header -->
<div data-role="content">
<p>Page content goes here.</p>
</div><!-- /content -->
<div data-role="footer">
<h4>Page Footer</h4>
</div><!-- /footer -->
</div><!-- /page -->
</body>
</html>
View page template
A single HTML document can contain multiple "pages" that are loaded together by stacking multiple divs with a data-role
of "page"
. Each "page" block needs a unique id (id="foo"
) that will be used to link internally between "pages" (href="#foo"
). When a link is clicked, the framework will look for an internal "page" with the id and transition it into view.
Here is an example of a two "page" site built with two jQuery Mobile divs navigated by linking to an id placed on each page wrapper. Note that the ids on the page wrappers are only needed to support the internal page linking, and are optional if each page is a separate HTML document. Here is what two pages look like inside the body
element.
<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>I'm first in the source order so I'm shown as the page.</p>
<p>View 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>I'm the second in the source order so I'm hidden when the page loads. I'm just shown if a link that references my id is beeing clicked.</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>
View multi-page template
PLEASE NOTE: Since we are using the hash to track navigation history for all the AJAX "pages", it's not currently possible to deep link to an anchor (index.html#foo
) on a page in jQuery Mobile, because the framework will look for a "page" with an id
of #foo
instead of the native behavior of scrolling to the content with that id
.
The id
attribute of all your elements must be not only unique on a given page, but also unique across the pages in a site. This is because jQuery Mobile's single-page navigation model allows many different "pages" to be present in the DOM at the same time. This also applies when using a multi-page template, since all "pages" on the template are loaded at once.
Although the page structure outlined above is a recommended approach for a standard web app built with jQuery Mobile, the framework is very flexible with document structure. The page, header, content, and footer data-role elements are optional and are mostly helpful for providing some basic formatting and structure. The page wrapper that used to be required for auto-initialization to work is now optional for single page documents, so there isn't any required markup at all. For a web page with a custom layout, all of these structural elements can be omitted and the AJAX navigation and all widgets will work just like they do in the boilerplate structure. Behind the scenes, the framework will inject the page wrapper if it's not included in the markup because it's needed for managing pages, but the starting markup can now be extremely simple.
Note: In a multi-page setup, you are required to have page wrappers in your markup in order to group the content into multiple pages.
Also Note: If your body contains no data-role="page"
divs, jQuery Mobile wraps the entire contents of the body within a page div as explained above.
jQuery Mobile is using jQuery's wrapAll()
method to do this which looks for any script tags inside the content being wrapped, and loads each script source via XHR.
If scripts are present in the body, the browser ends up loading them twice.
We therefore strongly recommend that jQuery Mobile documents with scripts in their body also contain a div
with data-role="page"
.
When using single-page templates, you can prefetch pages into the DOM so that they're available instantly when the user visits them. To prefetch a page, add the data-prefetch
attribute to a link that points to the page. jQuery Mobile then loads the target page in the background after the primary page has loaded and the pagecreate
event has triggered.
Alternatively, you can prefetch a page programmatically using $.mobile.loadPage()
:
$.mobile.loadPage( pageUrl, { showLoadMsg: false } );
Keeping lots of pages in the DOM quickly fills the browser's memory, and can cause some mobile browsers to slow down or even crash. jQuery Mobile has a simple mechanism to keep the DOM tidy.
Whenever it loads a page via AJAX, it flags the page to be removed from the DOM when you navigate away from it later (technically, on the pagehide
event). If you revisit a removed page, the browser may be able to retrieve the page's HTML file from its cache. If not, it re-fetches the file from the server. (In the case of nested listviews, jQuery Mobile removes all the pages that make up the nested list once you navigate to a page that's not part of the list.)
If you prefer, you can tell jQuery Mobile to keep previously-visited pages in the DOM instead of removing them. This lets you cache pages so that they're available instantly if the user returns to them.
$.mobile.page.prototype.options.domCache = true;
Alternatively, to cache just a particular page, you can add the data-dom-cache="true"
attribute to the page's container.
To keep all previously-visited pages in the DOM, set the domCache
option on the page plugin to true
, like this:
pageContainerElement.page({ domCache: true });
Note that the contents of the first page isn't removed from the DOM, only pages loaded in via AJAX. Pages inside a multi-page template aren't affected by this feature at all - jQuery Mobile only removes pages loaded via AJAX.