Navigation-With-Css-And-Jquery/: Working Version Here
Navigation-With-Css-And-Jquery/: Working Version Here
Navigation-With-Css-And-Jquery/: Working Version Here
com/tutorials/javascript-ajax/create-a-cool-animated-
navigation-with-css-and-jquery/
Overview
The menu we’re building can be seen in the screenshot below. You can also see the final
working version here.
Rough sketch
Creating Resources
Writing down the HTML
Writing down the CSS
Creating the animation using jQuery
We will split the page into 4 parts, header, navigation and content header and the rest of
content
The header area will be simple <div> container
The navigation area will be split into several <div> container matching the menu item.
Now most of the time we use <ul><li> container but since every menu item is unique,
I do not see the advantages of using <ul><li> so I am going to use <div> container
instead.
So to summarize it
1. <!-- header section-->
2. <div id="header"></div>
3.
4. <!-- navigation section-->
5. <div id="navigation" class="container">
6. <div><a href="#">home</a></div>
7. <div><a href="#">about</a></div>
8. <div><a href="#">services</a></div>
9. <div><a href="#">solutions</a></div>
10. <div><a href="#">contact</a></div>
11. </div>
12.
13. <!-- container section-->
14. <div class="container">
15. <div id="content-title"></div>
16. <!-- rest of the content -->
17. </div>
It might help to show the directory structure I’m. The directory structure is as follows:
Step 2: Resources
I assume you have basic knowledge in dealing with Photoshop, so I will not give too detail
instruction on creating the resources.
There are several things we need to create.
Header background
Content Title
Navigation
Background stripe
Note that if you wish to skip this step you can download the full zip of files at the end of the
tutorial and extract my copies!
Okay, let’s create the header background. Open up Photoshop and create a 1×181 px canvas, or
you can create it larger and then crop the image.
Create a layer and give it a linear gradient with Foreground to Background preset for 171px, this
will be the main gradient.
Create another layer and give it a linear gradient with Foreground to Transparent preset for about
10px at the bottom of the first layer for some shadow effect.
Here is what it should look like, it is 100×181 px that I later crop to 1×181 px.
Next, we will create the content title. Again, open up Photoshop and create 934×284 px.
Create Rounded Rectangle using the appropriate tool, select the created shape, create a new
layer, add a gradient and give it some drop shadow.
Then we will have something like this:
Save this as ‘content-title.png’ in ‘img’ folder.
Now let us create the resources needed by the navigation. We need two sets of navigation and a
white box.
The white box is simple. Just create a rounded rectangle of about 98px x 58px and paint it with
white. Ensure the background is transparent.
For the navigation item, open your Photoshop and create a 490px x 58px document.
Create a rounded rectangular with about 98px x 58px and put some text in it. We will need two
copy of each text.
I applied a little drop shadow on each text, this of course is optional. You can choose your own
colors to put here.
Now simply duplicate this layer along the horizontal line. Apply different colors and text.
Save this as ‘nav.jpg’ in ‘img’ folder.
Finally, for the background stripe I have simply used an online tool called the Stripe Generator.
The output looks like this:
1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org
/TR/xhtml1/DTD/xhtml1-strict.dtd">
2. <html xmlns="http://www.w3.org/1999/xhtml">
3. <head>
4. <title>slick animated menu</title>
5. <!--our CSS file-->
6. <link rel="stylesheet" href="css/main.css" type="text/css" />
7. <!--jQuery library-->
8. <script type="text/javascript" src="js/jquery.js" ></script>
9. <!--jQuery plugin, we’ll get to this later-->
10. <script type="text/javascript" src="js/jquery-bp.js" ></script>
11. <!--Our animation script-->
12. <script type="text/javascript" src="js/navigation.js" ></script>
13. </head>
14. <body>
15. <div id="header"></div>
16. <div id="navigation" class="container">
17. <div id="home"><a href="home">home</a></div>
18. <div id="about"><a href="about">about</a></div>
19. <div id="services"><a href="services">services</a></div>
20. <div id="solutions"><a href="solutions">solutions</a></div>
21. <div id="contact"><a href="contact">contact</a></div>
22. </div>
23. <div class="container">
24. <div class="content">
25. <div id="content-title"></div>
26. <!-- the rest of the content-->
27. </div>
28. </div>
29. </body>
We will also have a white box on top of every navigation item appear, when we hover over the
menu or a menu item is being selected, so we will need another <div> container for that. The
final HTML will look like this:
1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org
/TR/xhtml1/DTD/xhtml1-strict.dtd">
2. <html xmlns="http://www.w3.org/1999/xhtml">
3. <head>
4. <title>slick animated menu</title>
5.
6. <link rel="stylesheet" href="css/main.css" type="text/css" />
7.
8. <script type="text/javascript" src="js/jquery.js" ></script>
9. <script type="text/javascript" src="js/jquery-bp.js" ></script>
10. <script type="text/javascript" src="js/navigation.js" ></script>
11. </head>
12. <body>
13. <div id="header"></div>
14. <div id="navigation" class="container">
15. <div id="home" class="pri-nav"><div><a href="home">home</a></div></div>
16. <div id="about" class="pri-nav"><div><a href="about">about</a></div></div>
17. <div id="services" class="pri-nav"><div><a href="services">services</a></div></
div>
18. <div id="solutions" class="pri-nav"><div><a href="solutions">solutions</a></div>
</div>
19. <div id="contact" class="pri-nav"><div><a href="contact">contact</a></div></div
>
20. </div>
21. <div class="container">
22. <div class="content">
23. <div id="content-title"></div>
24. <!-- the rest of the content-->
25. </div>
26. </div>
27. </body>
Save this as ‘index.html’. Up to this point we have this as our HTML page:
Step 4: CSS
Let us apply some basic style to the Web page. We will start by defining the background and
adding a header area.
1. body {
2. background: url(../img/body-bkg.jpg) repeat scroll;
3. margin: 0;
4. padding: 0;
5. }
6.
7. .containe r{
8. margin: 0pt auto;
9. width:950px;
10. }
11. #header {
12. background: url(../img/hdr-bkg.jpg) repeat-x scroll;
13. height:181px;
14. }
1. #navigation{
2. height:60px;
3. }
4.
5. #home, #home div,
6. #about, #about div,
7. #services , #services div,
8. #solutions, #solutions div,
9. #contact, #contact div {
10. height:80px;
11. position:absolute;
12. width:97px;
13. float:left;
14. }
15.
16. #home, #about, #services, #solutions, #contact{
17. background-image: url(../img/nav.jpg);
18. background-attachment: scroll;
19. background-repeat: no-repeat;
20. top:171px;
21. }
22.
23. #home{
24. background-position: 0px -25px;
25. margin-left:6px;
26. }
27.
28. #about{
29. background-position: -98px -25px;
30. margin-left:105px;
31. }
32.
33. #services{
34. background-position: -196px -25px;
35. margin-left:204px;
36. }
37.
38. #solutions{
39. background-position: -294px -25px;
40. margin-left:303px;
41. }
42.
43. #contact{
44. background-position: -392px -25px;
45. margin-left:402px;
46. }
47.
48. #home div, #about div, #services div, #solutions div, #contact div {
49. background-image: url(../img/white.jpg);
50. background-attachment: scroll;
51. background-repeat: no-repeat;
52. background-position: 0px -60px;
53. }
Now we have :
One problem, the <a href> link appears on top of the menu items, let’s remove that with a huge
text indent – effectively taking it off the screen.
Add this to our style sheet.
1. .pri-nav a{
2. display:block;
3. text-decoration:none;
4. text-indent:-30000px;
5. }
1. #header{
2. background: url(../img/hdr-bkg.jpg) repeat-x scroll;
3. height:181px;
4. position:absolute;
5. z-index :100; /* ensure the header is on top of navigation area */
6. top: 0px;
7. left:0px;
8. width:100%;
9. }
Now because we used a .png file with transparency, it should look like this:
Perfect! Let’s add the content so we can get to our animation script.
1. .content{
2. margin-top:160px;
3. }
4.
5. #content-title{
6. background: url(../img/content.jpg) no-repeat scroll;
7. height:323px;
8. position:absolute;
9. width:100%;
10. }
There is something we need to understand before proceeding. I quote from the plugin
documentation:
Due to some browser bugs (i.e. Firefox, you have to set your (initial) background-position inline:
<div style=”background-position: 10px 20px”></div>
- Of course you can achieve this with JavaScript (jQuery), too:
$(‘#background’).css({backgroundPosition: ’10px 20px’});
Okay now that we understand that, let’s start. We will set the backgroud position style for every
item in the beginning of our script.
1. // id for each of our menu items
2. var nav = [ '#home', '#about', '#services', '#solutions', '#contact' ];
3. $(document).ready(function(){
4. setBkgPos();
5. });
6.
7. function setBkgPos()
8. {
9. for ( i = 0; i < nav.length; i++ ){
10. $(nav[i]).css({backgroundPosition: i*(-98) + 'px -25px'});
11. $(nav[i] + ' div').css({ backgroundPosition: '0px -60px'});
12. }
13. }
Now we will bind 3 events to each of the menu items. We can do this by invoking the bind
function.
1. $(document).ready(function(){
2. setBkgPos();
3.
4. // bind the event to function here
5. for ( i = 0; i < nav.length; i++ ) {
6. $(nav[i]).bind( 'mouseover', mMouseOver );
7. $(nav[i]).bind( 'mouseout', mMouseOut );
8. $(nav[i]).bind( 'click', mClick );
9. }
10. });
Whenever a user hovers over the navigation item our script will call ‘mMouseOver’ function.
When the user hovers out of the navigation item our script will call ‘mMouseOut’ function.
And when the user clicks on the navigation item, our script will call ‘mClick’ function.
On 'Mouse Over':
Change the navigation menu image (glow) and change the cursor to pointer.
The navigation will move up a bit.
The white box will move down.
The white box and the navigation menu will both down.
The navigation menu and the white box will move up to its final position.
And change the navigation menu image to its original state.
1. function _getHPos( id )
2. {
3. for ( i = 0; i < nav.length; i++ ){
4. if ( '#' + id == nav[i] ){
5. return i*(-98);
6. }
7. }
8. return 0;
9. }
10.
11. function mMouseOver(e)
12. {
13. $(this)
14. // stop any animation that took place before this
15. .stop()
16. // step 1. change the image file and change the cursor
17. .css({backgroundImage: 'url('+site_url+'img/nav-over.jpg)',cursor: 'pointer'})
18. // step.2 move up the navigation item a bit
19. .animate({ backgroundPosition:'(' + _getHPos( this.id ) +'px -30px}'},"fast",
20. // this section will be executed after the step.2 is done
21. function(){
22. $(this)
23. .children()
24. // step. 3 move the white box down
25. .animate({backgroundPosition:'(0px -40px)'},20)
26. // step 4. move the white box down
27. .animate({backgroundPosition:'(0px -20px)'},"fast");
28. $(this)
29. // step 4. move the navigation item down
30. .animate({backgroundPosition:'(' + _getHPos( this.id ) +'px 50px)'},"fast")
31. // step 5. move the navigation item to its final position
32. .animate({backgroundPosition:'(' + _getHPos( this.id ) +'px 25px)'},"fast");
33. // store the parent element id for later usage
34. var parent = this;
35. $(this)
36. .children()
37. // step 5. move the white box to its final position
38. .animate( {backgroundPosition:'(0px -45px)'},"fast",
39. // this section will be executed after the step.2 is done
40. function(){
41. // step.6 change the image to its original image
42. $(parent).css({backgroundImage: 'url(img/nav.jpg)'});
43. });
44. });
45. }
46.
1. The _getHPos is use to adjust the horizontal background position navigation for each
item.
For example, the ‘Home’ item background will start from 0, the ‘About’ horizontal
background position starts from -98px, and so on.
2. Also notice that early in the function we invoke the ‘stop’ function. We do this to ensure
whatever animation was running before the ‘mouse over’ event has stopped.
Why? We will add another animation later on for the ‘mouse out’ event.
Now let us suppose the user hover over an item and then quickly move the mouse pointer
some place else and again quickly hover over the same item.
If we do not stop the animation before each event, there will be a delay because some part
of the animation will be queued or even worse the animation will become inconsistent
and annoy the user.
Now that is done. Let's create "story board" for the 'mouse out' event
On 'Mouse Out':
The code:
1. function mMouseOut(e)
2. {
3. $(this)
4. // stop any animation that took place before this
5. .stop()
6. // step.1 move down navigation item
7. .animate({backgroundPosition:'(' + _getHPos( this.id ) +'px 40px )'}, "fast",
8. // this section will be executed after the step.1 is done
9. function(){
10. // step.2 white box move really fast
11. $(this).children().animate({backgroundPosition:'(0px 70px)'}, "fast");
12. // step 3. move navigation item up
13. $(this).animate( {backgroundPosition:'(' + _getHPos( this.id ) +'px -40px)'}, "fast",
14. // this section will be executed after the step.3 is done
15. function(){
16. // step 4. move navigation item ot its original position
17. $(this).animate( {backgroundPosition:'(' + _getHPos( this.id ) +'px -25px)'}, "fast",
18. // this section will be executed after the step.4 is done
19. function(){
20. // move white box to its original position, ready for next animation
21. $(this).children().css({ backgroundPosition:'0px -60px'});
22. })
23. })
24. })
25. .css({backgroundImage: 'url(img/nav.jpg)', cursor: ''});
26. }
Almost there! Now we need to handle when a user click on the navigation item.
1. function mClick(e)
2. {
3. location.href = this.id;
4. }
Of course you can point to wherever location you see fit here. This particular function will direct
your browser to [current_url]/[navigation_id] so for ‘home’ it will be ‘[current_url]/home’, for
‘about’ it will be ‘[current_url]/about’ and so on.
Of course we need an indicator when we are already on a page. For that we need another CSS
class.
We will call that class ‘active’. For instance if we are now at 'home' the HTML file will become:
1. <div id="about" class="pri-nav active"><div><a href="about">about</a></div></div>
and so on.
So now the idea is after a page is loaded our script will check to see which navigation item has
the ‘active’ class.
We then apply an animation effect. And we need to ensure any other events ( ‘mouseover’,
‘mouseout’, ‘click’) will not cause any animation effect on this 'active' item.
For that we need to change our code a bit. Here is the complete code after the changes:
1. var site_url = '';
2. var nav = [ '#home', '#about', '#services', '#solutions', '#contact' ];
3.
4. $(document).ready(function(){
5. setBkgPos();
6.
7. for ( i = 0; i < nav.length; i++ ) {
8. $(nav[i]).bind( 'mouseover', mMouseOver );
9. $(nav[i]).bind( 'mouseout', mMouseOut );
10. $(nav[i]).bind( 'click', mClick );
11. }
12.
13. for ( i = 0; i < nav.length; i++ ) {
14. // element with ‘active’ class will start animation
15. if ( $(nav[i]).get(0).className.indexOf('active') >= 0 ){
16. $(nav[i])
17. .animate({ backgroundPosition:'(' + _getHPos( nav[i] ) +'px -30px}'},"fast",
18. function(){
19. $(this)
20. .children()
21. .animate({backgroundPosition:'(0px -40px)'},20)
22. .animate({backgroundPosition:'(0px -20px)'},"fast");
23. $(this)
24. .animate({backgroundPosition:'(' + _getHPos( nav[i] ) +'px 50px)'},"fast")
25. .animate({backgroundPosition:'(' + _getHPos( nav[i] ) +'px 25px)'},"fast");
26. var parent = this;
27. $(this)
28. .children()
29. .animate( {backgroundPosition:'(0px -45px)'},"fast",
30. function(){
31. $(parent).animate({backgroundPosition:'(' + _getHPos( parent.id ) +'px 25px)'},
"fast");
32. $(parent).css({backgroundImage: 'url(img/nav.jpg)'});
33. });
34. });
35. break;
36. }
37. }
38. });
Finished!