How To Create iPhone-Style Navigation (Part I)
Posted on February 11, 2010 and got 37 shouts so farIn this tutorial I’d like to talk about how to make an iPhone style navigation using jQuery and CSS. This tutorial is divided into 2 parts. In part 1 we discusses the conception of the menu, the techniques to implement that concept and to tidy up your menu display so as to make it more like what iPhone has. In part 2, we discusses how to implement the script that we have made in part 1 on our daily life by adding AJAX (here we call the content from the menus that is chosen dynamically) and cookie (in order to make the chosen menu be appeared in the right order though we refresh the page).
The Basic of Showing Menus Technique
For showing the menu like what we want, we have to make use of a masking technique like what we have done on the previous post. To make the menu that we have chosen display the next content in horizontal slide, we need a div content (containing a menu or a content) on the left side of that chosen menu. Take a look at this one:

The picture above explains explicitly how a div content being placed next to the first div content. Those div contents will moved to the right side or the left side according to the user action. When a menu is clicked to show a content, the div slider will shift the position and the div content will be like this:

Each div content, except div content #1, will have a back button to move the div content back to its position (by moving it horizontally of course). If you click the back button on above picture, the div slider will shift to the right and show the previous content.

One Movement Only
If you see on the first picture, there are so many div contents next to the div content #1. If we choose div content #3 for example, the div slider will move twice (from div content #1 to div content #2 and then from div content #2 to div content #3). So, how could we make it make one movement only? What if we have 50 div contents and we want to open the last one? Should we make 51 movements? Absolutely not! It’s just so simple to solve this junk. Take a look at this picture:

Let’s say that we choose div content #5. All div contents except div content #1 will be moved to the right side, each as wide as certain distances, and then we move div content #5 right to the next of div content #1.

See the picture. All div contents move to the right side and then div content #5 shift to the right side of div content #1, so we only need to shift the div slider once onto the left side and the div content will be displayed without making several movements.

It’s Time for Coding, Yippee!
You have already known the techniques above, right? Now you will implement it easily to the script. Just like what I said before, we will use jQuery and CSS to get the things done. CSS will take an important part in making a masking technique.
I wonder if we could minimalize the using of pictures. Well, since the CSS has the background gradient property, we will make use of it for our menu header background and menu list when it is hovered (for webkit users, you can use -webkit-gradient property whereas firefox mania can use -moz-linear-gradient).
We all know that the using of CSS will reduce the display compatibility on certain browsers, that’s why we have to use an image as the background for the header and the menu list. Check this out:
HTML
The function of the div container –don’t forget to use iPhone background on it– is to store all of your divs, from sliders to div contents while div binder is made to arrange the div content’s position. Div slider, on the other hand, is a div that we use to make right or left movement so that the div content that we are chosen can be displayed appropriately.
Div additional-block is a group of div contents that we are going to display. Each div has a unique id representing the menu list. Div header, just like its name, represents the header of contents displayed (it can be the title or headline of the content).
There is nothing special from menu list except the link that leads us to div’s id that we want to display. In short, the link represents certain div content.
CSS
#container { margin-left: auto; margin-right: auto; margin-top: 2%; padding-top: 5.85em; padding-left: 1.8em; background: url('images/iPhone.png') top left no-repeat; width: 300px; height: 504px; position: relative; overflow: hidden; text-align: left; } .binder { background: #e8e8e8; float: left; width: 247px; height: 370px; position: relative; overflow: hidden; } .header { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#AAB8C9), to(#6E84A2), color-stop(.5,#6E84A2)); background: -moz-linear-gradient(0% 65% 90deg,#6E84A2, #AAB8C9, #AAB8C9 100%); font-size: 14px; color: #fff; height: 30px; padding: 0 10px; text-shadow: 0px 1px 0px #000; text-align: center; position: relative; } .additional-block { float: left; width: 247px; height: 370px; position: absolute; } .menu li:hover { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#4185F4), to(#194FDB), color-stop(.6,#194FDB)); background: -moz-linear-gradient(0% 65% 90deg,#194FDB, #4185F4, #4185f4 100%); cursor: pointer; } .menu li:hover a.has-child { background: url('images/arrow-hover.png') center right no-repeat; } .menu li a { display: block; width: 227px; } .menu li:hover a { color: #fff; text-shadow: 0px 1px 0px #000; } .has-child { background: url('images/arrow.png') center right no-repeat; } .has-child:hover { background: url('images/arrow-hover.png') center right no-repeat; } .back { margin-top: .5em; background: url('images/prev.png') bottom left no-repeat; position: absolute; display: block; height: 15px; width: 10px; cursor: pointer; }In order to make the div contents be put in a good arragement on the side of div content #1, we fill the float property with ‘left’ and the position with ‘absolute’. If you realize, you’ll see that each div contents will superimpose one each other with this setting. To put it in order, we can use javascript by automatically setting the left margin of each div content.
To make the div contents that are not chosen be not displayed and not floating, we fill the position property of div container and div binder with ‘relative’ and overflow with ‘hidden’.
JavaScript
$(document).ready(function() { //Initializing variable defaultWidth = 247; //pixels transition = 500; //millisecond //Reset margin and set margin for each div content function function resetMargin(width) { divLeftMargin = 0; $('.additional-block').each(function() { thisLeftMargin = divLeftMargin + 'px'; $(this).css('margin-left', thisLeftMargin); divLeftMargin = divLeftMargin + width; }); } //Now reset and each div content margin resetMargin(defaultWidth); //Find sub-menu for each menu and show the arrow $('.menu a').each(function() { thisHref = $(this).attr('href'); if($(thisHref).length > 0) { $(this).addClass('has-child'); } }); //If user click the menu $('.menu a').click(function(event) { //Disable default action event.preventDefault(); //Initialize all variable and object selectedDiv = $(this).attr('href'); selectedMargin = $(selectedDiv).css('margin-left'); selectedParent = $(this).parents('.additional-block'); sliderMargin = $('.slider').css('margin-left'); slidingMargin = (parseInt(sliderMargin) - defaultWidth) + 'px'; //If selected menu have a sub menu if(selectedMargin.length > 0) { //Add 'back' button to the selected div content $(selectedDiv).children('.header').prepend('').bind('click', function () { //And bind action to this button selectedParent = $(this).parents('.additional-block'); sliderMargin = - (parseInt(selectedParent.css('margin-left')) - defaultWidth) + 'px'; $('.slider').animate({marginLeft: sliderMargin}, transition); }); //If selected div content's margin more than or equal than default width if((parseInt(selectedMargin) - defaultWidth) >= defaultWidth) { //Move the selected div content after the menu's div content, reset and set all div content margin and slide them selectedParent.after($(selectedDiv)); resetMargin(defaultWidth); $('.slider').animate({marginLeft: slidingMargin}, transition); } else { $('.slider').animate({marginLeft: slidingMargin}, transition); } } }); });First, we set the default width and transition time for the next code. Our width default could be 247px (suitable with the width of div content that we have set on CSS) and our transition time could be 500 milisecond so that the transition between div will not be too fast.
Then we make a function called ‘resetMargin’ with argument width. This function is very useful for choosing all div contents (with class additional-block) and then put it in order horizontally by setting the left margin of each div content. The value of each left margin for div content will be generated automatically by counting the left margin from each div that put in order and so on until all div content get its position.
To check whether a sub-menu can be displayed or not, we need to check the menu itself, fetch the link and then check the whole webpage: is there any div content with that id link? If there is, we will add class has-child (to show an arrow symbol). If there is not, then forget it.
If a menu is clicked, we will turn off the default function of it. And then:
- Get a div content which is appropriate with chosen menu.
The function is as cache, since this object will be used frequently on the next code.- Get margin from div content
The function is to decide the position of div content. It also used to calculate the space between div content #1 and chosen div content.- Get div content from chosen menu (parent element)
The function is to search from which div content this link menu comes, so that we can be able to move div content we have chosen.- Get the margin position of div slider.
It will be useful to determine how far div slider will be moved.- Count the margin position that will be moved.
By this calculation, we will get the movement distance of div slider.We check whether the menu that we chosen has a sub-menu or not. If not, it will be left that way, if it yes, we will add a back button on the chosen div content (that is going to be displayed) and then the button will be given a function of left movement (to the previous div content).
We check again on what position the div content will bi displayed. If more than or equal to the default width, we will set the div content position by using the technique I have explained before and then show it by shift it. If less than the default width, we will only need to shift it because the div content has already been on the next of displayed div content. Here is the final result :
Okay, so far we have done with the script. Don’t forget to join to the next tutorial (part 2) and thanks for reading! You can get regular useful updates about web-stuff by subscribing webstuffshare RSS feed or webstuffshare FREE Email subscription. If you like this post, your sharing and feedback would be very appreciated
![]()


What They Shouts
Shout Something
The Artist
Popular Post
Stuff & Community News
Tags Collection
keren, coba gambar iphonenya bisa di rotate, buat gallery keren… jadinya kalo gambarnya bentuk memanjang, tinggal putar gambar iphonenya.. hihi…
Wew mantab, gut aidea mam
Jadi pengen nyoba mam, tengkyu yak
sipp.. klo cewek gw cipok lw yat :-p
@bot4x :p
mantab gan !
@arief Tengkyu udah mampir
mantaBB gan
hehehe bdw itu ilustrasi dapet dari mana bang?
@Ainamaie bikin ndiri pake potosop mi
huahaha payah deh, dikau salah menuliskan namaku bang…
ErrRRrr… hehehe
This article has been shared on favSHARE.net. Go and vote it!
Hi… Love this tutorial… thankx
I like everything about apple products.. love this,..
It’s awesome, but it doesnt work on IE8
Check it out! it gives “invalid argument”. I am using jquery 1.4.2
@korayem Thank you korayem, but unfortunately i don’t support IE. Is there any problem you got on any other browser? Let me know.
Never mind, it’s a buy in jQuery and I’ve fixed it. It’s working smoothly now in IE..WOOOHOOO!!!
Thanks!
Getting issue with IE. What does’nt it like?
Hi
can I make it to span 100 percent in width
I wan to use this in website that I am developing
I’ve gotten everything working great, thanks…. but the only problem I’m have is my slide transitions are not very smooth.
I have placed my own content which is more than just nav like you have, but I was wondering if you know how to fix this.
If you have an iphone you can see it in action at
http://give.rivercitywc.com/iphone
It runs smooth in safari on my computer just not on the iphone.
@Aniq :
Of course you can.
@Jason Isaacs :
Yours are great but unfortunately I don’t have one, sorry
Hello,
Great article, can I just ask something?
I’m trying to use this with dynamic content, so I wanted to have a vertical scroll, when needed the script shows browser scroll bar, at this moment it cuts the content at defined container height, but if I use height=100%; it doesn’t work.
Any sugestion?
Thanks
Hi,
I am working in sencha .After integrating this in sencha ,jquery is not working in sencha!!!
Does sencha support this jquery?
Thanks
Dineshkumar
Hi,
Can any one plz send Ext Js for above Java script?
Thanks
Dinesh
Hi,
This is quite interesting, thanks for the article. One thing I noticed is that your code is adding multiple “” and event listeners every time the user visits the same page.
Thanks
RF
I actually tried to say your code is adding multiple back buttons (spans) – the blog removed my markup.
Awesome.. Appreciate your work. Thanks a lot for sharing.
Hi Hidayat
Love this system! Perfect for iPhone versions of website admin systems!!
My only problem / question is how to simulate or tell the system to slide to a specific target using js.
For example – if I’m using ajax to check something and need the sys to go to the same place as if I’d clicked – how to I do this?
I’ve tried giving the link an id=”egid” and then calling:
document.getElementById(‘egid’).trigger(‘click’);
I’m a bit out of my depth – can you make a suggestion?
Thanks,
Matt
Hi Matt,
If you want to use your apps for iPhone or any mobile version, I suggest you to use this http://www.jquerymobile.com/
To use ajax you can read this tutorial (part 2 from this tutorial) :
http://www.webstuffshare.com/2010/02/iphone-style-navigationajax-rotate-part-ii/
Have a nice coding!
Hi Hidayat,
thank’s for sharing this – nearly perfect, beside the bloody IE8 complaining about “Invalid Object”.
add the following lines to the CSS file, and IE8 is happy.
.slider {
margin-left: 0px;
}
Regards,
Max
Hi Max,
Kudos! and thank you for finding the bug and hack for IE!
Hi Hidayat,
This is very awesome! I trying to use this on my website project.
I face some issue when doing with this.
When i got a lot of menus in 1 level, i got no option to select those menu at the bottom. Can you add in some effect like “easing on mouseover” if the menu is more then parent height?
another issue is when i try to put 3 iphone-style navigation at the same page, it doesn’t work individually.
Thanks~
Regards,
Chong Wang
Hi Chong Wang,
You can use this plugin to add scrollbar on your parent div http://baijs.nl/tinyscrollbar/
Im am using this slider menu on a portal that looks like a desktop with corporate apps, (sponsor wall flip) and when fliping an icon i show app description link to productive enviorment and a MORE menu, that can have link to tool blog, wiki, documentation, help, etc… looks very neat (will share when done) but how to i make a menu item link open the tool web page, click got disabled and only slides (i dont javascript much)
thanks i just found a way to do it
just wrap this code
if (selectedDiv.indexOf(“#”) != 0) {
window.open(selectedDiv);
} else {
…..
….. if(selectedMargin.length > 0) {
…… }
…
}
arround
It’s awesome Thanks
I’m have question. How configure this script to remember last open submenu when open link this way
if ( (selectedDiv.indexOf(\’#\’)) != 0)
{
window.location = selectedDiv;
}
When page reload menu start from main menu
Now I use this menu
http://www.dynamicdrive.com/dynamicindex17/ddaccordionmenu-bullet.htm
When page reload I have select last open submenu.
Hello,
I use this menu in a web page, but the problem links to pages that do not work must be changed in the javascript to have clickable links.
thank you
Hello,
I do a lot of tests, and I think this menu deserve to be designed to implement a menu in a web project, because the javascript is not done at all for that, I did some more tests to open a link in a modal box in other menu it works well but not this one, especially at the level html design it is very easy to implement, in fact it should be a javascript type as the iPod menu of filamentgroup while keeping your style is great.
I thanks for the bug fixing for IE 7,8