Welcome to our free jQuery Mobile tutorial. This tutorial is based on Webucator's jQuery Mobile course.
The much smaller screens on mobile devices present unique challenges for user interface design. We'll look at how jQuery Mobile adopts successful UI design patterns and offers useful UI widgets to give visitors to your pages easy access to a wide variety of content and interactions.
In this lesson, we'll cover a range of useful UI elements - from toolbars to lists to sliders to form elements to grids - built in to jQuery Mobile. All of these UI widgets are based on traditional HTML5 (or HTML) tags, sometimes with data-x attributes or specific classes added to present the element in a mobile-optimized fashion.
Many jQuery Mobile pages will show a header and footer toolbar, at top and bottom, respectively. The header bar typically shows the page title and, often, a navigation bar; the header bar on some interior pages may show a "back" button. The footer bar is usually the last element on a page.
All of the jQuery Mobile pages we've seen so far have had a header toolbar - it would be nice if, on interior pages, we included a "back" button for the user to easily return to the previous page. Adding a "back" button is pretty easy: insert data-add-back-btn="true" to the data-role="page" div. We can also easily add one or two buttons to the header toolbar. Add buttons as children of the data-role="header" element and use appropriate classes to align the buttons to the left or the right of the title (ui-btn-left or ui-btn-right) and to set the buttons as inline and mini. (Note that versions of jQuery Mobile prior to 1.4 positioned the first included button left and the second one right, with all buttons included in the headers styled as "mini" and "inline"; this behavior has been deprecated as of version 1.4.)
The left screenshot shows a page with a header with attribute data-add-back-btn="true". The right screenshot shows a header with two buttons, links to "Home" and "Page 1".
Open WidgetsUI/Demos/toolbars/index.html in a mobile browser and in a file editor to view the code, to view this example.
The div with id page1 has attribute data-add-back-btn="true" - this adds the back button to Page 1.
<div data-role="page" id="page1" data-add-back-btn="true">
Page 2's page div doesn't have attribute data-add-back-btn="true"; instead, we add the buttons "manually" to the header:
<div data-role="header"> <a href="#home" class="ui-btn-left ui-btn ui-btn-inline ui-mini ui-corner-all ui-btn-icon-left ui-icon-home">Home</a> <h2>N&B: Page 2</h2> <a href="#page1" class="ui-btn-right ui-btn ui-btn-inline ui-mini ui-corner-all ui-btn-icon-left ui-icon-grid">Page 1</a> </div>
Footer toolbars work pretty much the same as headers and are a logical place to put contact information, navigation elements, or other show-on-every-page content. Check out WidgetsUI/Demos/toolbars/footer.html - we've added several buttons, with the appropriate classes, to each of the interior pages (#page1 and #page2). Wrapping the buttons in a div with attributes data-role="controlgroup" and data-type="horizontal" displays the buttons with no separation. We add a bit of padding to the footer, around the buttons, on page 2 with class="ui-bar".
Unlike in headers, as we saw above, the classes ui-btn-left and ui-btn-right do not work to position buttons in footers, because they do not account for the possible presence of text, navbars, and and other elements often present in footers. If needed, you can use custom CSS to position the buttons.
<div data-role="footer"> <a href="#home" class="ui-btn ui-corner-all ui-btn-inline ui-mini ui-btn-icon-left ui-icon-home">Home</a> <a href="#page2" class="ui-btn ui-corner-all ui-btn-inline ui-mini ui-btn-icon-left ui-icon-arrow-r">Page 2</a> </div>
Page 1's footer, shown above, has links to the Home page and to Page 2; we've chosen appropriate icons with the data-icon attribute.
<div data-role="footer" class="ui-bar"> <div data-role="controlgroup" data-type="horizontal"> <a href="#home" class="ui-btn ui-corner-all ui-btn-inline ui-mini ui-btn-icon-left ui-icon-home">Home</a> <a href="#page1" class="ui-btn ui-corner-all ui-btn-inline ui-mini ui-btn-icon-left ui-icon-arrow-r">Page 1</a> </div> </div>
Adding a div with attributes data-role="controlgroup" and data-type="horizontal" around the buttons in the footer creates a grouped set of button on Page 2. Note that we also add class ui-bar to the footer to give extra padding around the buttons.
jQuery Mobile offers a basic navbar widget that will show up to five items horizontally across the page; adding more than five items will cause the navbar to wrap to multiple lines, with the items displayed two-to-a-row. Navbars are typically (though need not be) added to headers or footers.
Navbars are coded as unordered lists of links wrapped in a container element (typically a div) with a data-role="navbar" attribute. Set one of the links to the active (selected) state by adding class="ui-btn-active" to the a tag.
Open WidgetsUI/Demos/toolbars/navbars.html in a mobile browser and in a file editor to view the code. We add a navbar to the header of the home page, and to the footer of each of the two interior pages:
Each navbar is an unordered list of links, wrapped in a div with attribute data-role="navbar". jQuery Mobile automatically splits each navbar link into one-third of the width of the page. We use class="ui-btn-active ui-state-persist" on the on-state nav item appropriately for each page; the ui-state-persist class specifies that the "active" state of the button should persist if the user were to refresh the page.
<div data-role="navbar"> <ul> <li><a href="#home">Home</a></li> <li><a href="#page1" class="ui-btn-active ui-state-persist">Page 1</a></li> <li><a href="#page2">Page 2</a></li> </ul> </div>
jQuery Mobile offers several options for the positioning of toolbars. By default, toolbars use the "inline" positioning mode: headers and footer sit in the flow of the document - header at top, content below it, and footer at bottom.
jQuery Mobile also offers several other toolbar positioning modes. Adding attribute data-position="fixed" to the toolbar fixes the header (at the top) or footer (at the bottom) on the page. The toolbar stays fixed while the content scrolls. Tapping the content toggles the visibility of the fixed toolbars. Open WidgetsUI/Demos/toolbars/fixed-standard.html to see this "fixed" mode in action.
Note that this only works in browsers that support CSS position: fixed (most desktop browsers, iOS5+, Android 2.2+, and others). For browsers that don't support fixed positioning, the toolbars will remain positioned in flow, at the top or bottom of the page.
Add data-position="fixed" and data-fullscreen="true" attributes to a toolbar for "fullscreen" positioning. Similar to "fixed" mode, "fullscreen" positioned toolbars sit on top of existing content, with a slight transparency. Open WidgetsUI/Demos/toolbars/fixed-fullscreen.html to see "fullscreen" positioned toolbars.
The following screenshots show fixed toolbars on the left and fixed fullscreen toolbars on the right. Note that you can see some of the content behind the toolbars in the fullscreen example; the fixed-fullscreen toolbars hide when the user taps the screen.
In this exercise, you will add navbars to pages for the Nan & Bob's Online site.
We add a navbar to the header of the "Home" page, with appropriate
data-icon values to show an icon at the top of each link. We use
class="ui-btn-active" to make the "Home" link active for this page.
Each of the non-home pages gets a navbar in its footer, with
class="ui-btn-active" again used to make the relevant link active for each page.
Whether it is a list of blog entries, products to purchase, or site navigation items, lists play an important role in web content. A listview in jQuery Mobile is coded as a simple unordered list (a <ul> element) with attribute data-role="listview". By default, jQuery Mobile stretches each item, button-like, to fill the screen; adds appropriate padding; and adds a right-arrow icon at right. Unordered lists of links without the data-role="listview" attribute still work of course, but don't get the styling:
Open WidgetsUI/Demos/lists/index.html in a mobile browser and in a file editor to view the code. The unordered list is in the first (#home) page:
<ul data-role="listview"> <li><a href="#about">About Us</a></li> <li><a href="#proprietors">Proprietors</a></li> <li><a href="#history">History</a></li> </ul>
Note that we use the data-add-back-btn="true" attribute on each of the non-home pages' headers: this automatically adds a button to the upper left of the header of the page:
<div data-role="page" id="about"> <div data-role="header" data-add-back-btn="true"> <h2>N&B: About Us</h2> </div> <div class="ui-content" role="main"> <p>About us paratus validus foras at praesent usitas probo sino esse vicis sagaciter ratis feugait loquor.</p> </div> <div data-role="footer"> <h3>123 Fake St. Anywhere USA</h3> </div> </div>
See the jQuery Mobile docs for details on how to customize the back button.
You can, of course, use ordered lists (ol, instead of ul) to display items with numbers at left. Lists of items without links display much like vertically stacked buttons; the text for these nonlinked lists is slightly smaller than on the link-ful lists, to save space. Check out WidgetsUI/Demos/lists/ordered.html to view this:
Nesting child ul or ol list items inside a list allows you to create nested lists. Clicking (tapping) a list item that contains a child list generates a new page populated with the title of the parent in the header and the list of child elements. Lists can be nested multiple levels deep.
Open WidgetsUI/Demos/lists/nested.html in a mobile browser and in a file editor to view the code. The left screenshot shows the parent list; the right shows the page automatically added by jQuery Mobile to display the nested list:
Here's the code:
The "About Us", "History", and "Proprietors" items are nested inside the "About" item - tapping "About" brings the user to a virtual page displaying the nested list, from which the user can tap a link to get to a page. Note that we include a script tag in the head of the page, linking to jquery.mobile.nestedlists.js, which we downloaded from the link given above.
Some content dictates more than one action per list item - a user might be asked, for instance, to edit or delete a given item from a content-management admin screen. jQuery Mobile's split button list addresses this situation: adding a second link inside the list generates a vertical divider line with two clickable regions.
Open WidgetsUI/Demos/lists/split-button.html in a mobile browser and in a file editor to view the code:
This page lists the two owners of Nan & Bob's. Clicking the name of the owner brings the user to a detail page; clicking the icon at right opens a mailto: link to send an email. Note the use of attribute data-split-icon="info" on the ul to specify the icon to use. You can also add attribute data-icon to each individual list item to add a specific icon to each, instead of adding the same icon to all list items.
<ul data-role="listview" data-split-icon="info"> <li><a href="#nan">Nan</a><a href="mailto:email@example.com">Contact</a></li> <li><a href="#bob">Bob</a><a href="mailto:firstname.lastname@example.org">Contact</a></li> </ul>
Longer lists are more useful with subheaders/dividers - a company directory, for instance, might show a nonclickable list item labeled "A" at the start of all of the "A" names, etc. Add a li item with data-role="list-divider" to add a divider item to your list:
Open WidgetsUI/Demos/lists/dividers.html in a mobile browser and in a file editor to view the code:
<ul data-role="listview"> <li data-role="list-divider">About Us</li> <li><a href="#about">General</a></li> <li><a href="#proprietors">Proprietors</a></li> <li><a href="#history">History</a></li> <li data-role="list-divider">Contact Info</li> <li><a href="#contact">Contact</a></li> <li><a href="#directions">Directions</a></li> </ul>
A great way to offer users easy access to longer lists is with jQuery Mobile's built-in list search filter. Simply add the data-filter="true" attribute to the list ul, and voila: jQuery Mobile filters the list to match the user's typing:
Open WidgetsUI/Demos/lists/filter.html in a mobile browser and in a file editor to view the code:
<ul data-role="listview" data-filter="true"> <li><a href="#book"><em>Cry, the Beloved Country</em>, Alan Paton</a></li> <li><a href="#book"><em>The Kite Runner</em>, Khaled Hosseini</a></li> <li><a href="#book"><em>The Time Traveler's Wife</em>, Audrey Niffenegger</a></li> <li><a href="#book"><em>Things Fall Apart</em>, Chinua Achebe</a></li> <li><a href="#book"><em>The Trojan Women</em>, Euripides</a></li> <li><a href="#book"><em>Twelfth Night</em>, William Shakespeare</a></li> </ul>
The filter works on ordered (ol) lists, too.
Note that we've added a custom CSS rule in the head of the document - setting white-space: normal for a tags inside of li tags forces the text to wrap rather than being cut off.
There's even more you can do with lists: formatting text, adding list bubbles (to display, for example, a count of comments for each blog post in a list), controlling icons and thumbnail images, and more. See the jQuery Mobile docs for more information.
In this exercise, you will add a list of books for purchase to the Nan & Bob's Online site.
We use a split-button list to present the books available for purchase to the user. Attribute
data-filter="true" adds the filter functionality; attribute
data-split-icon="plus" sets the right-side icon.
The first link (pointing to the appropriate detail page) in each list item includes an image, which displays flush left, and the book title and author. The second link (pointing to the confirm dialog) in the list item becomes the icon.
The dialog presents two buttons: "yes" points to the checkout page; "no" points back to the book-list page.
Presenting content blocks that users can toggle open and closed helps improve the user experience; saving even a few pixels of screen real estate on mobile devices' small screens is a good thing. Add data-role="collapsible" to any container element - a div, say - and jQuery Mobile displays a "collapsible", collapsed by default:
Open up WidgetsUI/Demos/collapsible/index.html to check out the code and view the live demo. Here's the code from the screenshot above:
<div data-role="collapsible"> <h3>Content</h3> <p>Quis, te camur loquor augue nimis vero paratus te, quis, neo delenit. Luptatum, blandit esca roto iriure enim fatua dolore lobortis. Ad ut, similis pecus te, sudo, nisl praesent suscipit. Acsi, eu ne esse ut euismod genitus, nisl.</p> <p>Tation eligo regula saepius amet duis macto quis ideo praesent dolore ut sudo inhibeo.</p> </div>
Notice that jQuery Mobile labels the collapsible's toggle bar with the text contents of the first header element (H1 - H6) inside the data-role="collapsible" and sets the icon at left with plus and minus sign for the open and close actions. The element is collapsed by default (i.e., on page load); use attribute data-collapsed="false" to display the element as open when the page loads.
You can set the element as "mini" (data-mini="true") to display the collapsible slightly smaller. You can position the icon on the toggle bar with attribute data-iconpos="right".
Add a container element with attribute data-role="collapsible-set" around multiple collapsibles and jQuery Mobile displays a collapsible set. Open one collapsible and the rest of its set-mates collapse - a useful way to present a volume of content in a small space:
Open up WidgetsUI/Demos/collapsible/set.html to view the code and view the live demo. Here's the code from the screenshot above:
<div data-role="collapsibleset"> <div data-role="collapsible"> <h3>Item 1</h3> <p>Item 1 tation eligo regula saepius amet duis macto quis ideo praesent dolore ut sudo inhibeo.</p> </div> <div data-role="collapsible"> <h3>Item 2</h3> <p>Item 2 tation eligo regula saepius amet duis macto quis ideo praesent dolore ut sudo inhibeo.</p> </div> <div data-role="collapsible"> <h3>Item 3</h3> <p>Item 3 tation eligo regula saepius amet duis macto quis ideo praesent dolore ut sudo inhibeo.</p> </div> </div>
Multicolumn layouts usually aren't a good idea on mobile devices' small screens, but there are times when you will need to display items in two, three, or more columns. Grid cells in jQuery Mobile have no color, no border, and no padding nor margin.
To lay out elements in a grid, wrap them in a container element (usually a div) with class ui-grid-a for two columns, ui-grid-b for three columns, etc. Each element inside the container gets a class ui-block-[a-z], with the a element (i.e., the element with class ui-block-a) at left, the b element next, etc.
Open WidgetsUI/Demos/grids/index.html in a mobile browser and in a file editor to view the code. This page show a two-column grid and a three-column grid - each with one row - and a four-column grid with two rows:
Here's the code:
<h3>Two Columns</h3> <div class="ui-grid-a"> <div class="ui-block-a">Col 1</div> <div class="ui-block-b">Col 2</div> </div> <h3>Three Columns</h3> <div class="ui-grid-b"> <div class="ui-block-a">Col 1</div> <div class="ui-block-b">Col 2</div> <div class="ui-block-c">Col 3</div> </div> <h3>Four Columns</h3> <div class="ui-grid-c"> <div class="ui-block-a">Col 1,1</div> <div class="ui-block-b">Col 1,2</div> <div class="ui-block-c">Col 1,3</div> <div class="ui-block-d">Col 1,4</div> <div class="ui-block-a">Col 2,1</div> <div class="ui-block-b">Col 2,2</div> <div class="ui-block-c">Col 2,3</div> <div class="ui-block-d">Col 2,4</div> </div>
Classes ui-grid-a, ui-grid-b, ui-grid-c set two-, three-, and four-column grid layouts. Note that, with the multirow layout for the four-column grid, the first element of the second row of elements starts over with class ui-block-a.
In this exercise, you will add collapsible content for the "Eats" page on the Nan & Bob's Online site.
We add a
div with attribute
data-role="collapsible-set" in the "Eats" page, with three
divs, one for each baked good item for purchase. Each item is labeled with an
<h3> tag and contains a two-column grid, showing the item description on the left and the purchase button on the right.
We change the "No" button in the confirm dialog to point to the previous page by adding the attribute
data-rel="back", effectively becoming a "close" button for the dialog, which allows us to reuse the dialog both for "books" and for "eats".
jQuery Mobile forms, like standard HTML forms, are wrapped in a form tag, with action and method attributes: <form action="page.php" method="post">. Because jQuery Mobile uses a single-page navigation model, be sure that each form element has a unique id - different from any other element in the site.
Each form control element should be paired with a meaningful label, connected by the label's for attribute and the form control's id:
<label for="fname">First Name:</label> <input type="text" name="firstname" id="fname">
If using the HTML5 placeholder attribute - to display an instruction in the form element itself - you may want to hide the label. Rather than delete the label (and make your pages harder to use for visitors employing a screen reader or other assistive technology), apply the jQuery Mobile convenience class ui-hidden-accessible:
<label for="fname" class="ui-hidden-accessible">First Name:</label> <input type="text" name="fname" id="fname" placeholder="First Name">
The screenshot below shows the result of viewing WidgetsUI/Demos/forms/index.html in a mobile device:
Each field - each form control or set of related form controls - is wrapped by a
div with attribute
data-role="fieldcontain". This framework aligns the input and associated label next to each other, and breaks to stacked block-level elements below about 480px. The fieldcontainer will also add a thin bottom border to act as a visual field separator.
The first two fields ("Text Input" and "Text Input (mini)") show the difference between regular and mini, with the latter being slightly smaller.
The "Textarea" field is coded and displays much like a traditional desktop textarea. The "Search Input" field is an HTML5 search-type
input; note how jQuery Mobile styles the display with a search icon.
The "Flip switch" element, a common UI element on mobile devices, is used for on/off or true/false fields. One can either drag the handle or tap one side of the switch. It is coded as a
select with attribute
data-role="slider". Note that we hide the label for this element with class
The next form control, a
select with label "Select menu", is a standard drop-down menu.
The "Slider" element is a slider, an
input of type
range - a useful control for allowing users to pick from a range of values. Add a
step attribute to the form element to quantize the values to a given step increment.
The next two sets of form elements illustrate the difference between vertical and horizontal checkboxes: vertically displayed checkboxes show a checkbox, whereas in horizontally displayed checkboxes the element acts more like a button, with a color showing the on (checked) state. In both cases, we use a
fieldset with attribute
data-role="controlgroup" to group the checkboxes; we use the attribute
data-type="horizontal" for the horizontal display.
Radio buttons allow for one, and only one, element to be selected, as with traditional desktop radio buttons. A
fieldset, with attribute
data-role="controlgroup", groups the radio buttons.
A "Submit" button completes the form.
In this exercise, you will add a checkout form to the Nan & Bob's site.
Adding the form tag with attribute
data-ajax="false" allows us to submit the form without using Ajax - and thus to submit the form to the
We add appropriate fields for each piece of submitted information:
input type="text"for the first and last names.
textareafor the shipping address and notes.
datefor the email and date-of-birth fields, respectively.
selectfor the shipping options.