Making CSS Rollover Buttons
In this tutorial, we'll show you how to create easy, search-engine-friendly rollovers, using nothing but HTML, CSS and images. No JavaScript or IMG tags in sight!
Rollovers are a nice way to add visual feedback to your website's buttons. As a visitor moves their mouse over a rollover button, it changes to indicate that it's clickable.
In the bad old days of HTML, the only way to create a rollover was to use JavaScript to swap the two button images. While this works, it does rely on JavaScript being enabled in the browser. It also adds a fair bit of code bloat to the page, meaning longer download times, and more coding for you.
Thankfully, these days you can create a nice rollover effect using pure CSS; no JavaScript required! Roll your mouse over this button, which is created using just HTML, CSS and a single image:
So how's it done? Well, it all centres around the :hover pseudo-class in CSS. Using this pseudo-class, you can style a link both in its normal state and in its hover (rollover) state. By making the link a block element and giving it a background image, we can turn the link into a button. We then simply jiggle the background image around to create the rollover effect.
The button image
The trick to making this type of rollover work smoothly is to have both the normal and rollover images stacked in a single GIF image, with the rollover state below the normal state. Here's our button image - it's 107 pixels wide and 46 pixels tall:

On the one hand, this is slightly inconvenient as it means you have to use Photoshop - or a similar image editor - to create a single image containing your normal and rollover images. You can't just grab normal and rollover button images from somewhere and use them as they are. Of course, this is no problem if you're creating your site design in Photoshop anyway.
On the other hand, this approach avoids issues with flickering and preloading, which we'll talk about in more detail at the end of the article. It's also nice, in a way, to have both the normal image and the rollover image packaged within a single image file; it's easier to keep track of your button images, and you only have half as many image files to worry about!
The markup
The HTML for our button is wonderfully simple. In fact it's just a link with an id, and a span element wrapped around the link text:
<a id="emailUs" href="#" title="Email Us"><span>Email Us</span></a>
We give the link an ID - in this case, "emailUs" - which allows us to style the link via our CSS. We also place the actual link text inside a span element. This means that we can hide the link text with our CSS and display the image instead, yet the link still looks like a regular text link to browsers not using the style sheet - such as a search engine spider or a text-only browser, for example.
The CSS
To turn our regular text link into a rollover button, we apply the following CSS:
#emailUs
{
display: block;
width: 107px;
height: 23px;
background: url("emailUs.gif") no-repeat 0 0;
}
#emailUs:hover
{
background-position: 0 -23px;
}
#emailUs span
{
display: none;
}
First we change our emailUs link from an inline element to a block element with display:block. This allows us to give the link a width and height, as well as set our button image as a background. We set the width of the link element to the width of our GIF image, but we set its height to half the height of the GIF; that is, the height of one of the button images. This means that just the top, normal button image appears within the link by default. The bottom, rollover button image is cut off, and therefore remains hidden.
Then we select the link's :hover pseudo-class to style our rollover state. This is simply a matter of shifting our background GIF up by 23 pixels, or half the GIF's height. This hides the normal button image above the top of the link element, and reveals the rollover button image within the link; you can think of it as sliding the GIF upwards within the "window" of the link. When the visitor moves their mouse away from the link again, the button GIF slides back down 23 pixels, returning to its default position, with the normal button image revealed within the link.
Finally, all we need to do is set display: none on the span element inside the link, hiding the link text for browsers that support CSS and images.
And that's all there is to it!
Creating more than one button
If you want to create many rollover buttons in the page - for example, as part of a menu - copy and paste the HTML and CSS, giving each button a unique id in both the HTML and the CSS and, of course, changing the background image for each button in the CSS.
Alternatively, you could style the link text to be in the centre of your button image, rather than being hidden; you'd then only need one (blank) button image for all the menu options. The tradeoff with this approach is that you lose some control over the look of your button text, and the buttons don't generally look as nice.
The rationale
You may be wondering why we've taken the approach of having both the normal and rollover images within the one GIF image. In fact you could easily rework the CSS to include two separate images, as follows:
#emailUs
{
display: block;
width: 107px;
height: 23px;
background: url("emailUsNormal.gif") no-repeat 0 0;
}
#emailUs:hover
{
background: url("emailUsRollover.gif") no-repeat 0 0;
}
What you'll find, though, is that the button "flickers" the first time you move the mouse over it, as the browser fetches emailUsRollover.gif from the server. In other words, most browsers don't preload the background image of the :hover state. By combining both our normal and rollover states in a single GIF, we're forcing the browser to "preload" the rollover state image as it fetches the normal state image.
An alternative approach might be to use a JavaScript preloader, or a hidden img element in the page, to preload emailUsRollover.gif, but then we're kind of losing the point of having a non-JavaScript, pure-CSS rollover!
A nicer alternative is WebCredible's Trifecta button. This uses an inline img element in the markup for the normal state, and a background image in the CSS for the rollover state. To create the rollover effect, it toggles the visibility of the inline image. This means that both images are preloaded with the page, avoiding any flickering effects. It also uses markup to display the button text - a technique that we touched on earlier - meaning that you only need one button image pair for a whole menu.
The drawbacks with the Trifecta button are, firstly, that it requires an extra div wrapped around your link, and secondly, that you end up with an inline image in your markup. Having an inline image means more markup, and also means that you're fairly committed to having image buttons on your site; it's harder to replace your image rollovers with pure CSS versions, or with simple text links, later. However, the Trifecta is a nice solution if you like the idea of separate rollover images.
There's one gotcha with the single-GIF approach, and that's when using our old friend, Internet Explorer 6. If you have this browser set to always fetch files from the server (Tools > Internet Options > Temporary Internet Files > Settings > Check for newer versions of stored pages: Every visit to the page), you'll get horrid flickering each time you move the mouse over the button.
Luckily, it tends to be mainly Web developers that have this setting enabled; most visitors leave IE6 at its default setting of "Automatically".
Microsoft fixed this problem in IE7. Also note that the Trifecta button doesn't suffer from the problem in IE6.
Follow Elated
Related articles
Responses to this article
20 most recent responses (oldest first):
You can have multiple elements with the same class on a page, but not with the same id on a page.
eg.
<a class="selected">link 1</a> <a class="selected">link 2</a>
is OK, but
<a id="selected">link 1</a> <a id="selected">link 2</a>
is not valid.
Does that help?
See http://www.elated.com/forums/topic/4685/#post18069 , which I think will answer your question.
Cheers,
Matt
Thanks for this tutorial, as a Web Design student it was very useful, something they didn't teach me at uni.
However, I have a problem. I am adding drop down lists into the mix, so that when I hover over a menu item, a list drops out from under it. When I move my mouse onto the drop down list, the menu item moves back into its original position.
Here is the site so you can see what I mean, just move your mouse along the turquoise bar below the logo, and then down into the menu list:
http://numyspace.co.uk/~unn_l203081/Project/Plugged_In.html
Any way that I can keep the menu item position changed as if I was still hovering over it?
Thanks
Mike

#menubar a.home {
display: block;
width: 164px;
height: 45px;
background: url("images/home_hover.gif") no-repeat 0 0;
}
#menubar :hover a.home { << this "a.home" is the key!
background-position: 0 -45px;
}
Thanks again for this tutorial
Mike
[Edited by mykkenny on 08-Apr-10 16:23]
Thanks for the great tut!
I am using this in a menubar that is called into each page by PHP.
I would like to have an active state for buttons that are clicked -
However this means that I can't have an active state class that is specific to each page. (The idea being that I have a standalone menubar that works in each page.)
Is there any way round this? For example a class that is triggered by some code on each page? (effectively turning a class on and off??)
Cheers!
David
hello…I am kind of a newbie with css and yes I do understand and succesfully made that single rollover but I want to have multiple image rollovers in one page and these multiple image rollovers should be connected or should i say side by side to conserve space so how can I do that? pls. do reply and thanks in advance! I want it to be connected left to right. It's also not intended for a menu they are just images with rollovers which I would like to link to separate links. pls. do reply thanks.
@bk_rik: Float the buttons left, eg:
#emailUs
{
display: block;
float: left;
...
I was successful at creating a horizontal menu navigation. I am having trouble with the background image and navigation bar. I am wanting to place the nav bar in a specific location on top of the back ground image. Here is the code I'm working with.
<style type="text/css">
#profile
{
display: block;
float:left;
width: 99px;
height: 44px;
background: url("http://img63.imageshack.us/img63/6553/profilenav.gif") no-repeat 0 0;
}
#profile:hover
{
background-position: 0 -44px;
margin-top: 0px;
}
#projects
{
display: block;
float: left;
width: 130px;
height: 44px;
background: url("http://img707.imageshack.us/img707/8943/projectsnav.gif") no-repeat 0 0;
}
#projects:hover
{
background-position: 0 -44px;
}
#proficiencies
{
display: block;
float: left;
width: 121px;
height: 44px;
background: url("http://img41.imageshack.us/img41/3634/proficienciesnav.gif") no-repeat 0 0;
}
#proficiencies:hover
{
background-position: 0 -44px;
}
#culture
{
display: block;
float: left;
width: 117px;
height: 44px;
background: url("http://img714.imageshack.us/img714/2085/culturenav.gif") no-repeat 0 0;
}
#culture:hover
{
background-position: 0 -44px;
}
#contact
{
display: block;
float: left;
width: 125px;
height: 44px;
background: url("http://img263.imageshack.us/img263/752/contactnav.gif") no-repeat 0 0;
}
#contact:hover
{
background-position: 0 -44px;
}
</style>
<div>
<a id="profile" href="#" title="Profile"><span></span></a>
<a id="projects" href="#" title="Profile"><span></span></a>
<a id="proficiencies" href="#" title="Profile"><span></span></a>
<a id="culture" href="#" title="Profile"><span></span></a>
<a id="contact"href="#" title="Profile"><span></span></a>
</div>
<img name="background" src="http://img192.imageshack.us/img192/5712/telioswelcome.jpg" width="520" height="1200" alt="" />
Thanks Matt
BTW you could create your rollovers using pure CSS - no images (such as http://img263.imageshack.us/img263/752/contactnav.gif) required. Just use text for the links, set the links to "display: block" and add some padding. Then change the background colour to blue using :hover. Much easier, and it'll speed up the page load too.
I created a mock up of the site with the navigation bar all as an image. What I am wanting to do is to remove the navigation bar in my image and insert a real navigation bar with the CSS code I've learned in this form.
I usually create unique div ids for each image and put an absolute positioning parameter on it so I can place it where I like on the page. I am wanting to put the navigation bar that I created above into a div and position that over my background image. I'm having trouble with this though.
Does that make more sense?

If you want to absolutely position each rollover then just use position: absolute along with the left and top properties - for example:
#profile
{
display: block;
position: absolute;
left: 10px;
top: 10px;
width: 99px;
height: 44px;
background: url("http://img63.imageshack.us/img63/6553/profilenav.gif") no-repeat 0 0;
}
Does that help?
It also works great using the top, center or bottom alignment as well...center being if you want to have a hover and active state in the image.
Heres what Ive been using for my rollovers (well, one form of it)
.home A:link {display:block; width:100px; height:25px; background: url(home.png) top;}
.home A:visited {display:block; width:100px; height:25px; background: url(home.png) top;}
.home A:hover {display:block; width:100px; height:25px; background: url(home.png) center;}
.home A:active {display:block; width:100px; height:25px; background: url(home.png) bottom;}
Heres an example of a 3 state image and the code above.
http://web77.org/codework/916-floatingsidemenu/
Works in every browser that Ive tried so far.
Thanks again for the idea
======================================
I use positioning myself
Heres an example...
http://web77.org/codework/902-website/
<div style="position:relative; width:500px; height:101px; left:50%; margin-left: -250px; margin-top:10px;">
<div style="position:absolute; top:0px; left:0px;" class="nav1"><a href="index.shtml">Home</a></div>
<div style="position:absolute; top:0px; left:100px;" class="nav1"><a href="contact.shtml">Contact</a></div>
<div style="position:absolute; top:0px; left:200px;" class="nav1"><a href="aboutus.shtml">About Us</a></div>
<div style="position:absolute; top:0px; left:300px;" class="nav1"><a href="community.shtml">Community</a></div>
<div style="position:absolute; top:0px; left:400px;" class="nav1"><a href="links.shtml">Links</a></div>
</div>
I had a question though.
If I want to build an image portfolio with lots of little CSS-styled rollovers, what do you think is the best way to organize them all? In a Div tag, in a UL list?
Also, what would the code look like if one were to do this?
Thanks again,
Asterion
I have installed this phpBB3 style on my forum.
http://www.awesomestyles.com/phpbb3-styles/demo/macinscott-3?l=en&version=
But it doesn't have rollover buttons. So I found your great article and I would like to change the buttons into rollover.
I have already the necessary "double" images, but I have no idea where to write the CSS and HTML codes you provide.
Should I paste this code
#emailUs
{
display: block;
width: 107px;
height: 23px;
background: url("emailUs.gif") no-repeat 0 0;
}
#emailUs:hover
{
background-position: 0 -23px;
}
#emailUs span
{
display: none;
}
into the file "stylesheet.css"?
Also, the code
<a id="emailUs" href="#" title="Email Us"><span>Email Us</span></a>
where should I paste it?
Into which html file, and where? At the end of the file, at the beginning?
Sorry, but I have no previous experience in CSS and HTML, but rollover buttons is something that I want to have in my forum.
Thank you very much.
[Edited by nikosda on 29-Jul-10 02:38]
You'll need to paste the 'a' tags wherever you want to have the rollover effects in the theme. That depends on what buttons you want to apply the rollover effect to, and the file(s) where the markup for those buttons are stored.
Post a response
Want to add a comment, or ask a question about this article? Post a response.
To post responses you need to be a member. Not a member yet? Signing up is free, easy and only takes a minute or two. Sign up now.