How To Build a Mobile Detail List Webapp in HTML5/CSS3
Published in Tutorials, Web DevelopmentThere are countless mobile applications which use list views in their UI. Both Android and iOS offer platform-specific designs to make building applications easier. But there is another template you can build with just typical HTML5 and CSS properties.
In this tutorial I want to introduce a method for building clean HTML5 mobile web applications. For the demo below I’ve limited the width at a maximum of 800px but you can theoretically scale to any browser size. This is what makes mobile web development so profitable – the amount of control you have over the user experience. You can follow along with the tutorial code and download a copy of my source files from the link below.
Live Demo – Download Source Code
Beginning the Document
I’m starting out with the HTML5 doctype and a few important tags in the head area. First the couple meta tags for X-UA-Compatible and viewport are needed to render properly on mobile screens. Also I’m including a reference to retina.js which is a 3rd party script for retina displays.
This will auto-detect when you are using an iPhone or iPad with retina support and automatically pulls images with the consistent filename. So for example we should create a high-resolution image named my-house@2x.jpg and then size down for standard resolution named my-house.jpg. It’s a bit of extra work but it pays off if you’re targeting a mobile audience.
<!doctype html> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>Simple Mobile Listview</title> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> <meta name="HandheldFriendly" content="true"> <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,user-scalable=no"> <link rel="stylesheet" type="text/css" href="styles.css"> <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> <script type="text/javascript" src="retina.js"></script> <!--[if lt IE 9]> <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script> <script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script> <![endif]--> </head>
There is another external script I referenced named CSS3-Media Queries. This will add support for responsive queries running older browsers before IE9. There are also older legacy versions which do not support @import and this script handles them correctly.
Generating a List View
Now inside the body section I am going to use an unordered list to create the markup. An alternative solution is using tables, but I feel these add a lot of unnecessary tags into the code.
<div id="container">
<ul>
<!-- row 01 -->
<a href="#"><li class="clearfix">
<img src="images/modern-castle-kitchen.png" alt="thumb" class="thumbnail">
<h2>Full-Room Mansion with Open Kitchen</h2>
<p class="desc">Rental located in Pheonix, AZ. 2 bedrooms 1.5 baths. </p>
<span class="price">$2,650/month</span>
</li></a>
<!-- row 02 -->
<a href="#"><li class="clearfix">
<img src="images/penthouse-with-bar.png" alt="Modern penthouse bar" class="thumbnail">
<h2>Modern Penthouse Highrise with Bar</h2>
<p class="desc">Rental located in New York City, NY. 1 bedroom 1 bath.</p>
<span class="price">$1,800/month</span>
</li></a>
So in my example the entire list is contained inside a wrapper div. Each list item is also wrapped by an anchor link with no href value. In any real mobile app you would link to additional pages possibly running over a framework such as jQuery Mobile.
Each internal item contains a thumbnail image which is floated onto the left side. The src attribute is targeting the standard image, but with our retina.js script these are automatically replaced on retina screens. Also the items are targeted rental listings, with a bit of detail.
Listview Styles
Now let’s turn attention over to the CSS stylesheet. We can quickly throw in some default CSS resets based on Eric Meyer’s popular article which does cover almost everything. One interesting piece to this webapp is the fixed navigation bar which follows you along down the page.
/** top header bar **/
header {
display: block;
position: fixed;
top: 0;
z-index: 9999;
height: 55px;
width: 100%;
max-width: 800px;
border-bottom: 1px solid #262422;
-webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.4);
box-shadow: 0 2px 2px rgba(0, 0, 0, 0.4);
background: #5a5955;
background: -moz-linear-gradient(top, #5a5955 0%, #51504c 50%, #494744 51%, #3f3d3a 100%);
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#5a5955), color-stop(50%,#51504c), color-stop(51%,#494744), color-stop(100%,#3f3d3a));
background: -webkit-linear-gradient(top, #5a5955 0%,#51504c 50%,#494744 51%,#3f3d3a 100%);
background: -o-linear-gradient(top, #5a5955 0%,#51504c 50%,#494744 51%,#3f3d3a 100%);
background: -ms-linear-gradient(top, #5a5955 0%,#51504c 50%,#494744 51%,#3f3d3a 100%);
background: linear-gradient(to bottom, #5a5955 0%,#51504c 50%,#494744 51%,#3f3d3a 100%);
filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#5a5955', endColorstr='#3f3d3a',GradientType=0 );
}
header h1 {
font-size: 2.4em;
font-family: Tahoma, Arial, sans-serif;
font-weight: bold; line-height: 55px;
text-align: center;
color: #efefef;
text-shadow: 1px 1px 0px #000;
}
Notice that I’m actually using CSS3 gradients to generate the top toolbar background. Also I’ve added a small drop shadow over the edge to appear floating on top of the content. Using position: fixed; with a z-index value will always keep this toolbar stationary when you scroll.
The internal container and list items are also using a set of fixed values. The height is always 90px so that our images aren’t floating too close on either side. Also I’m using more CSS3 gradients for a stripe from light grey to white.
#container { display: block; margin-top: 55px; }
#container ul { /* empty */ }
#container ul a li {
display: block;
width: 100%;
height: 90px;
border-bottom: 1px solid #b9b9b9;
border-top: 1px solid #f7f7f7;
background: #ebebeb;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ffffff) to(#ebebeb));
background-image: -webkit-linear-gradient(top, #ffffff, #ebebeb);
background-image: -moz-linear-gradient(top, #ffffff, #ebebeb);
background-image: -o-linear-gradient(top, #ffffff, #ebebeb);
background-image: linear-gradient(top, #ffffff, #ebebeb);
}
Anchor Link Hovers
Another tricky aspect to building this listview is handling user hover styles. Since the anchor link is located outside the entire list item we have to use nested CSS selectors.
#container ul a:hover li h2 { color: #7287b1; }
#container ul a:hover li p.desc { color: #757575; }
#container ul a:hover li {
background: #efefef;
background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#ffffff) to(#efefef));
background-image: -webkit-linear-gradient(top, #ffffff, #efefef);
background-image: -moz-linear-gradient(top, #ffffff, #efefef);
background-image: -o-linear-gradient(top, #ffffff, #efefef);
background-image: linear-gradient(top, #ffffff, #efefef);
}
There are so many options you can add to create a stunning hover effect. I’m updating some of the text colors to shine more brightly when you hover or tap a row on your mobile device. Also the background gradient will get brighter and should stand out compared to the other rows.
#container ul li img.thumbnail {
background: #fff;
display: inline-block;
float: left;
padding: 2px;
margin-top: 6px;
margin-left: 5px;
margin-right: 8px;
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
-moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);
}
The image thumbnails have a soft border to separate from this background gradient. The slight drop shadow also gives a popping-off-the-page effect which looks really nice.
Simple Responsive Queries
Since the layout was built with fluid widths we don’t need to update very much for smaller screens. But adding this tiny layer of responsive design helps to keep all the page elements adaptive.
/** basic media queries **/
@media only screen and (max-width: 480px) {
#container ul li h2 { font-size: 1.75em; }
#container ul li img.thumbnail { margin-top: 2px; }
}
@media only screen and (max-width: 320px) {
#container ul li p.desc { display: none; }
}
At first when the screen hits a width of 480px or less the list headings shrink down a bit in font size. We want to save room on mobile platforms where there isn’t as much screen real estate. Also the image thumbnails are moved up a bit towards the top. This has to do with offsetting the smaller text height where the screen is now more compact.
Finally if you’re running a mobile device in portrait mode then we want to completely remove the description lines. These are nice to have but ultimately unnecessary to the interface. And obviously you can feel comfortable editing in your own responsive styles as well.
Live Demo – Download Source Code
Conclusion
Beginners who are just getting started with web development should be able to follow along quickly. These techniques aren’t anything new but they come together brilliantly on a mobile device. You can locate our live demo on your mobile phone’s web browser and see how it responds to portrait/landscape modes.
Overall these are great techniques to follow if you’re interested in responsive web design. Mobile webapps aren’t as common as vendor-specific app stores. But these mobile apps are available to anyone in the world with Internet access. Truly a revolutionary period in mobile web development. If you have similar comments or questions about the tutorial feel free to share with us in the post discussion area below.
About the Author:
Jake is a freelance writer and frontend web developer. He can be found writing in many blogs on topics such as mobile interfaces, freelancing, jQuery, and Objective-C. Check out his other articles throughout Google and follow his tweets @jakerocheleau. Jake’s Google+ profile.




6 Responses
The idea behind the tutorial is nice, but the markup you’ve used is invalid. A
can only have
elements as its direct children. However, as you are using HTML5 instead of wrapping the
in
tags, you could just wrap the contents of the
instead.
On a side note you might want to take a look at your comment processing/styling. In my comment above I only used <code> tags which are usually displayed inline as opposed to <pre> tags which are often displayed in block.
Hey Tim thanks for your comments! Yes I think you’re correct, the list items should be the only thing embedded inside a UL element. Wrapping all the contents inside a list item, then wrapping inside an anchor link is the better more semantic solution! Great catch.
As for the code and pre tags you’re also correct, but I think the styles are borrowed from the blog theme. So that’s probably why your comment has block-line elements instead of inline code tags!
Thanks for reading and appreciate the feedback
Tim,
We’re working on some changes to the theme right now so we will try to address this issue.
Yes, I think the Tim has using li just after UL instead of within anchor text. But the entire code is good, easy to understand for beginner. However I am also a a beginner in Mobil apps but can you tell me how the retina.js works to identify the weather it is iPhone or iPod. As you have mentioned, it is a third party script but you are using relative path for this script ( type=”text/javascript” src=”retina.js” ) instead of full path of third party server.
@Neeraj you can download a copy retinajs from their website, just google and you’ll find it. Once you add that script to your document it’ll automatically check if the device is using a retina screen. If yes, then it’ll replace all your images by adding “@2x” to the end of the filename. This is the typical style guidelines put forth by Apple for developing apps in Xcode, so the retina.js script follows that pattern.
So for example you may have an image 50×50 named BigHouse.jpg. You should also include an imagine double the size(100×100) named BigHouse@2x.jpg. Retina.js will only replace your low-resolution image if the device supports a retina display – otherwise it’ll leave the images to their normal state.