Making a Slick MobileApp Website with jQuery & CSS

As a web developer, you have to bring creativity and attention to detail to your work. It is often the little things that leave a lasting impression to a visitor. Be it a lovable character illustration, or unique slideshow, it is usually not the information you present that is memorable, but the way you present it.

Today we are making a complete jQuery & CSS website for a fictional mobile application. It is going to feature semantic markup and a progressively enhanced slideshow effect. It will allow the user to see four of the most popular smartphones running the mobile app.

Step 1 – XHTML

When building websites it is important that you lay your code in a semantic way. This would include using tags for what they were supposed to be used for. You should use headings for titles, paragraphs for text (instead of generic divs) and lists where applicable.

mobileapp.html

<div id="page">

    <h1 id="logoh1"><a href="/" id="logo">MobileApp - the most useful mobile app!</a></h1>

    <div id="phoneCarousel">
    	<div class="previous arrow"></div>
        <div class="next arrow"></div>

        <div id="stage">
            <img id="iphone" class="default" src="img/phones/iphone.png" width="270" height="400" alt="iPhone" />
            <img id="nexus" src="img/phones/nexus_one.png" width="270" height="400" alt="Nexus One" />
            <img id="nokia" src="img/phones/nokia.png" width="270" height="400" alt="Nokia" />
            <img id="blackberry" src="img/phones/blackberry.png" width="270" height="400" alt="BlackBerry" />
        </div>
    </div>

    <img class="availableAppStore" src="img/available_on_the_appstore.png" width="230" height="80" alt="Available on the Appstore" />

    <div class="text">
    	<h3><img src="img/thumb.png" alt="MobileApp" width="114" height="114" class="thumb" />A wonderful app</h3>
        <p>Lorem ipsum dolor sit amet.. </p>
    </div>

    <div class="text">
    	<h3><img src="img/thumb.png" alt="MobileApp" width="114" height="114" class="thumb" />More awesome facts</h3>
        <p>Lorem ipsum dolor sit amet.. </p>
    </div>

</div>

This is all the markup that is used to display the website. The h1 heading holds a hyperlink which is styled as the logo (the logo image is set as the background of the hyperlink and a negative text indent is used to hide the text of the link).

After this we have the #phoneCarousel div and inside it are the arrows and the stage. The phone images inside the stage are rotated with jQuery as you will see in a moment.

Lastly we have the Available on the Appstore badge, and two blocks of text.

Slick MobileApp Website - Slideshow

Slick MobileApp Website - Slideshow

Step 2 – CSS

CSS is responsible for converting our semantic markup into a true website. Take a closer look at the #stage styles in the second part of the code, as these are what make the animation possible.

styles.css – Part 1

body{
	font-size:14px;
	color:#515151;
	background:url('img/bg.png') repeat-x #f6f8f9;
	font-family:'Myriad Pro',Arial, Helvetica, sans-serif;
}

#logoh1{ margin:40px 0 0;}

#page{
	/* This the main container div */
	width:1000px;
	min-height:700px;
	margin:0 auto;
	background:url('img/bokeh.jpg') no-repeat 0 120px;
	position:relative;
	padding-top:1px;
}

#phoneCarousel{
	/*	This is the carousel section, it
		contains the stage and the arrows */
	height:390px;
	margin:90px auto 120px;
	position:relative;
	width:800px;
}

#phoneCarousel .arrow{
	/* The two arrows */
	width:44px;
	height:44px;
	background:url('img/arrows.png') no-repeat;
	position:absolute;
	top:50%;
	margin-top:-22px;
	left:0;
	cursor:pointer;
}

#phoneCarousel .next{
	/* Individual styles for the next icon */
	background-position:right top;
	left:auto;
	right:0;
}

/* Hover styles */

#phoneCarousel .arrow:hover{
	background-position:left bottom;
}

#phoneCarousel .next:hover{
	background-position:right bottom;
}

After defining the  body styles we can move on to styling the #page div, which holds everything together. Its background image is offset 120px vertically, so it matches the background of the body, filling the full width of the page.

Next is the #phoneCarousel div. It has a relative positioning applied, so the stage (where all the animations take place) can be properly centered. The previous/next arrows are styled as well.

styles.css – Part 2

#logo{
	background:url('img/logo.png') no-repeat;
	height:40px;
	text-indent:-9999px;
	width:210px;
	display:block;
}

#stage{
	/* The stage contains the animated phone images */
	left:50%;
	margin-left:-350px;
	position:absolute;
	width:700px;
	height:100%;
}

#stage img{
	/* Hiding all the images by default */
	display:none;
}

#stage .default{
	/*	This class is applied only to the iphone img by default
		and it is the only one visible if JS is disabled */
	display:block;
	left:50%;
	margin-left:-135px;
	position:absolute;
}

#stage .animationReady{
	/* This class is assigned to the images on load */
	display:block;
	position:absolute;
	top:0;
	left:0;
}

.text{	margin-top:70px;width:700px;}

.text p,
.text h3{
	padding-bottom:15px;
	line-height:1.4;
	text-align:justify;
}

.text h3{	font-size:30px;}
.text p{	font-size:20px;}

.thumb{	float:left;margin-right:40px;}

.availableAppStore{float:right;}

In the second part of the stylesheet, we continue with the #stage styles. The phone pictures are hidden by default, so if JavaScript is disabled, the user is not left with a bunch of scattered images.

As you will see in the next step, the animation is achieved through changing the top and left CSS properties. For this to work, the images must be absolutely positioned. This is why the .animatonReady class is assigned on load with jQuery (if JS is disabled, this style would not be applied).

Lastly we style the text blocks, which explain details about our fictional MobileApp.

Text Blocks

Text Blocks

Step 3 – jQuery

When you click on one of the arrows, an animation starts, which uses sine and cosine calculations to move and scale down the images, creating the illusion of a circular movement. It is not as complicated as it sounds, as you can see for yourself from the code below.

script.js

$(document).ready(function(){

	var deg=0;

	/* Storing all the images into a variable */

	var images	= $('#stage img').removeClass('default').addClass('animationReady');
	var dim		= { width:images.width(),height:images.height()};

	var cnt = images.length;

	/* Finding the centers of the animation container: */
	var centerX = $('#stage').width()/2;
	var centerY = $('#stage').height()/2 - dim.height/2;

	function rotate(step,total){
		// This function will loop through all the phone images, and rotate them
		// with "step" degrees (10 in this implementation) till total > 0

		/* Increment the degrees: */
		deg+=step;

		var eSin,eCos,newWidth,newHeight,q;

		/* Loop through all the images: */
		for(var i=0;i<cnt;i++){

			/* Calculate the sine and cosine for the i-th image */

			q = ((360/cnt)*i+deg)*Math.PI/180;
			eSin		= Math.sin(q);
			eCos		= Math.cos(q);

			/*
			/	With the sine value, we can calculate the vertical movement,
			/	and the cosine will give us the horizontal movement.
			*/

			q = (0.6+eSin*0.4);
			newWidth	= q*dim.width;
			newHeight	= q*dim.height;

			/*
			/	We are using the calculated sine value (which is in the range
			/	of -1 to 1) to calculate the opacity and z-index. The
 			/	frontmost image has a sine value of 1, while the backmost
			/	one has a sine value of -1.
			*/

			// eq() extracts the image at the i-th position:

			images.eq(i).css({
				top			: centerY+15*eSin,
				left		: centerX+200*eCos,
				opacity		: 0.8+eSin*0.2,
				marginLeft	: -newWidth/2,
				zIndex		: Math.round(80+eSin*20)
			}).width(newWidth).height(newHeight);
		}

		total-=Math.abs(step);
		if(total<=0) return false;

		// Setting the function to be run again in 40 milliseconds (equals to 25 frames per second):
		setTimeout(function(){rotate(step,total)},40);

	}

	// Running the animation once at load time (and moving the iPhone into view):
	rotate(10,360/cnt);

	$('#phoneCarousel .previous').click(function(){
		// 360/cnt lets us distribute the phones evenly in a circle
		rotate(-10,360/cnt);
	});

	$('#phoneCarousel .next').click(function(){
		rotate(10,360/cnt);
	});
});

To start an animation you just need to call the rotate function with two arguments – a step, and a total rotation, both of which are numbers. Step can be negative, which would mean that the rotation is run in the opposite way. Each time the function is run, total is decremented with the absolute value of the step, and once it reaches zero the animation is stopped.

In a number of places in this code, you can see that I’ve used a specific calculation – 360/cnt. This is done to distribute the phones evenly (360 being the number of degrees in a circle).  This way you can add or remove images and they will be properly animated.

Slick MobileApp Website

Slick MobileApp Website

With this our Slick MobleApp Website is complete!

Wrapping it up

Today we made a complete jQuery & CSS website for a fictional mobile application. You are free to modify the code and use it any way you see fit. If you liked the tutorial be sure to subscribe to our RSS feed, follow us on twitter, or leave a comment in the section below.

Powered by Gewgley