I was recently working on a simple site for a friend and decided I wanted to put in a rollover effect for the navigation. Normally, using plain old Javascript, this wouldn’t be too much of a hassle (or is it?!). The catch is that I wanted to do it in jQuery, since that is what I am learning right now. You will notice throughout that I keep the HTML, CSS, and jQuery in separate files. It’s highly recommended that you keep the three separate from each other for numerous reasons; security probably, among the most important.
First off, I have to give credit where it is due. I did get some help on this based off of some other tutorials I ran across, mostly for image galleries and such. Hence the post following the credit!
- Tim Fletcher – a great tutorial for hovering over a thumbnail and making it appear in a larger viewport.
- WebDesignerWall.com – a nice image replacement gallery tutorial (#9) similar to Tim Fletcher’s.
- There was an awesome javascript version that I ran across and based the layout off of, but I can’t find that URL anymore. Sorry man!
As I will do with all the tutorials: Check out the demo and/or get the source code of the finished product.
Step 1: Setup the HTML
First things first, you need to setup your HTML:
<div id="container">
<div id="images">
<div id="fitness">
<img src="images/fitness-center.png" alt="Fitness" />
</div>
<div id="nutrition">
<img src="images/food.png" alt="Nutrition" />
</div>
<div id="additions">
<img src="images/supplements.png" alt="Additions" />
</div>
<div id="contact">
<img src="images/contact.png" alt="Contact" />
</div>
</div>
<div id="button">
<ul>
<li id="fitness">
<a href="index.html">FITNESS</a>
</li>
<li id="nutrition">
<a href="nutrition.html">NUTRITION</a>
</li>
<li id="additions">
<a href="additions.html">ADDITIONS</a>
</li>
<li id="contact">
<a href="contact.html">CONTACT</a>
</li>
</ul>
</div>
</div>
I’ve made an all-encompassing “container” div that has two other div’s in it: “images” (which holds the banner images that fade in/out) and “button” (which holds the navigation links. Notice each of them has their own corresponding id.
Step 2: Setting up the CSS
Styling the images and buttons is mighty important. After all, without some style, they are just plain old links!! So, in your CSS file, lets setup the buttons:
I also added some hover states for the buttons:
li#fitness:hover{
background:url(../images/fitness_hover.png) no-repeat;
}
li#nutrition:hover{
background:url(../images/nutrition_hover.png) no-repeat;
}
li#additions:hover{
background:url(../images/additions_hover.png) no-repeat;
}
li#contact:hover{
background:url(../images/contact_hover.png) no-repeat;
}
Lastly, you might notice that the buttons are not actually clickable right now. We need to edit the ‘a href’ css attribute:
/* make the buttons clickable by setting image dimensions */
div#button li a{
width:200px;
height:46px;
display:block;
}
Step 3: jQuery Time!
Now time for the jQuery action of fading out the image when we hover over the appropriate button. I’ll assume you know how to setup jQuery in page, but if you don’t now is the time to check out how jQuery works. To keep our markup, styles, and scripts seperate (which is how we want to do things), I created a file called ‘functions.js’. This is what I put in it along with the respective descriptions:**Initialize jQuery:
$(document).ready(function(){
This is the starting point for the hover function. Basically, I have asked jQuery to find any li elements under the button div:
$("div#button li").hover(function(){
When we find an li element, get the ‘id’ attribute tag and save it as a variable called elid:
var elid = $(this).attr('id');
We also hide the other images in the images div (with the banner images) to avoid any z-index conflicts, really for safety sake:
$("div#images div").hide();
This is really the workhorse line…we now say target the images div and find the div with the same id as the button we hovered over. That’s why we had the id on both the button and images as the same!! Now we are done, so we close the function and jQuery out:
$("div#images div#" + elid + "").fadeIn("slow");
});
});
Enjoy!
Thanks for the mention Justin!
Tim
Hi there – this sounds great … but the demo / links to source code do not work. Would you mind re-posting or sending to my email? Many thanks!
Hi David, sorry for the confusion! I re-posted and the links now work! Thanks for the heads up! Enjoy!
Ah – you’re a star … thanks for the swift response!
… what’s more, this is exactly what I’ve been looking for! SO simple …
Is there a reason to use JQuery for a rollover of this sort, when you could do the same with pure CSS, even multi-state?
I chose jQuery because I can control the fade in, fade out effect. Whereas, with CSS, the picture will just appear without the visual appeal of the fade. CSS would work fine, I went for eye candy.
Cool. Is it possible to put swfs into the image area and fade the swfs in and out?
Hi Bryan,
I would assume so! Try embedding your SWF in between the
<div></div>tags where the images would go. I’m no flash guy by any means, but I would imagine it would work just fine.Good Luck,
Justin
Awesome, Thanks!
Was just wondering if you could expand on the security issues of inline javascript?
Hi James,
The actual security concerns that I am aware of aren’t actually all that huge. Mainly, I hate for people to look at my code! A knowledgeable person could find a vulnerability and possibly exploit it. Call me paranoid…
Another huge reason to separating code, scripts, and styles is to minimize the bulkiness of the actual document. This will improve load time for the viewer (since it is really all about them!).
This is just what I’d like on my website! How can I get the container for the buttons to work in a horizontal format; say with the button running just above the main image?
Hi Lolley,
There are a couple things you will want to do to accomplish that.
#1. Change the list display from ‘none’ to ‘inline’ in your CSS – This way, the buttons are in a row, instead of a column. At that point, you will need to mess around with the placement of your button images:
#2. Next would be to position the banner to be below the buttons. If you use absolute positioning, you are going to get overlap, that’s ok. You will just need to move the banner down a little in your CSS. The other option is to use relative positioning, which will probably be the better alternative since you wont get overlap (you might need to tinker with the CSS some to get them perfect though)
All in all, changing the layout is strictly a CSS job, since the jQuery is not dependent of where the objects actually are on the page, instead, they just need to exist!
Have fun!
Justin
Thanks Justin! I shall have fun playing with the CSS!
oh dear! I fell at the first hurdle! Would you know why the ul{ list-style: inline; } might have no effect at all? I expected the buttons to be in a row even if the disappeared behind the disjointed image
Sorry for taking so long to get back to you Lolley, I have been crazy busy with my main job (the one that pays the bills)!
Anyways, on to the matter at hand: Are the buttons showing up at all? It’s possible that you will need to give each one a width, and position them absolutely.
I have tried it yet, but I’ll tinker around with the code on my side and post the CSS for you after success! Stay tuned!
Would it be possible to have this run automatically as soon as the page loads or similar? And also keep the rollover control too?
Sure! It should be a snap, but it might take some time to modify the code. One of the things I love about jQuery is the extensive Plugin repository. There is actually a plugin called ‘timer’ that should help you out here. I haven’t used the Plugin myself, so I’m not sure if it requires your HTML to be in a certain format or anything.
Good luck!
Thanks for this.
Just a minor nitpick…..
xHTML errors on divs with the same IDs. Well, it warns on it. Clean code which validates requires a single instance of an id on a page, not multiple ids that are the same. You’d be better off using classes rather than ids.
This great bit of code works wonderfully with classes as well. I’ve altered and tested.
It won’t fit your HTML and CSS here, but it’s the same structure with classes rather than ids.
Scott, great catch! You are very correct! Using the the same ids multiple times is not a good way to code! Thanks for the catch again!
Thanks! I have been looking for something like this! I’ve found that it works brilliantly in IE, but I have a small issue in firefox. One small change is that I made it switch by click rather than hover. And due to the “text-indent:-9999px;” I get that funky box outlining the linked area… which ends up going all the way across the screen. Any thoughts on how I could get rid of this would be much appreciated. I would be happy to send you a link to an example in PM.
Thanks!
Great tutorial!
Is there a way to supply and out, to return the image back to it’s original state when you are not hovering above on of the buttons?
Thanks!
John
[...] 22)Disjointed Rollovers with jQuery [...]
I’m trying to use this in my portfolio and have several separate galleries on the same page to roll over for each project, but it doesn’t seem to work if there is more than one. Is there any fix for this??
Hi,
doesnt bother You the fact You have at least two elements which have the same ID on the page ?
Hi,
I’m trying to implement Scotts version using classes not IDs, so I my page will validate. But not sure how to set it up he has: h1 a i need to apply the rollover to the below class on a div ?
help?
Thanks
Mark
<div class=”grid_1 project2-icon”></div>
Hi,
It would be possible, to have this “onClick” event instead of hovering..
I’m just a newbie…
Thanks..
is it posible to make animation fadein to fadeto or anything else