Create a Button with Hover and Active States using CSS Sprites

buttons

Too many designers neglect the click state (active: property in CSS) in web design, either because they’re unaware of it, underestimate the importance of it or are plain lazy. It’s a simple effect that improves usability by giving the user some feedback as to what they’ve clicked on but can also add depth to a design.

First, a look at the working button.

Button

This is the finished version of what will be built for this tutorial.

The Design

First thing we need to do is open up photoshop and create a design for the button. In this instance, we want to make it look very distinctive as a button:

button_static

Here it’s nice and big for the demo just to make things nice and clear but buttons shouldn’t need to big as big as this for the majority of uses.

Hover State Image

We need to have a slightly different style for when a user hovers over the button just to give them an indication that the button is interactive and therefore clickable, a standard web practice.

button_hover

The hover state is slightly darker than the normal static appearance but very noticeable difference when the user actually hovers over the element.

Click State Image

Now for the part that a lot of designers miss out on. We need a third state that changes when the user clicks on the button.

button_click

We’ve gone with the visual metaphor of an actual, physical button like ones you see on a mobile phone or mp3 player. The user then has an immediate recognition that a button performs a function when pressed.

A simple inner shadow, reversing the gradient and moving the text down one pixel achieves this effect nicely.

Sprite Image

The best practice is to combine all button states into one image and divide them out using CSS. This is because it:

  • reduces http requests resulting in faster transfers
  • prevents flickering effect caused by change of state by loading all states as one file

The CSS Code

Now that we’ve brought the different states into a single image we need to tell the browser what part of the image we want when necessary through CSS.

The static, initial state of the button is defined in CSS as follows:

a.button {
	background: url(../images/button.png) no-repeat 0 0;
	width: 186px;
	height: 52px;
	display: block;
	text-indent: -9999px;
}

The background image is positioned to the top and left with the width and height of the button being defined as to only show the top third of the sprite. The rest of the code is a simple image replacement technique on the <a> tag that has a class of ‘button’.

Hover State CSS

The hover state retains all properties and values with the exception of the background position as it’ll need to be pushed up to show the second part of the sprite as shown:

a.button:hover { background-position: 0 -52px; }

Changing the first value would result in the background image moving left and right along the X axis. Obviously we don’t want that so the image is moved upwards along the Y axis as a negative value of the height of the button itself. This moves the hover state of the sprite into view when the mouse hovers over the link.

Click State CSS

As you can probably guess the click state will basically be the same but moving the button up again as follows:

a.button:active { background-position: 0 -104px; }

Where Else Sprites Should be Used

If you’re navigation relies on images then all states can be combined into one big sprite image. Combining all buttons that appear one one page or a single section of your site into one image can be a great way to cut down on http requests. In fact I can show you the buttons I used on a recent project, all listed on a single page.

View the Buttons!

Just to show you what I mean about combining buttons onto a single sprite image take a look at this image. Buttons can be added to the end of the row without affecting any of the others.

Author Tom Kenny

I'm the creater of Inspect Element and currently work as a web designer for TUI Travel. You can view my portfolio and follow me on Twitter.

Discussion

  1. Sajid Iqbal says:

    In case of using single stripe for all buttons which is the easiest way to to know x & y position of a particular button?

  2. Hey lol what a co-incidence.. I just used the same technique to give a glow effect to my button on being clicked :P I think the CSS is the same because its quite simple but your visual effects rock and I suck at them :(

  3. Ooops sorry I forgot to mention that I set the height of the button as the height of the single button image. Hence instead of using numbers to change the image position, I just specified like this:

    #order-button{
    background-position: top;
    }
    #order-button:hover {
    background-position: center;
    }
    #order-button:active {
    background-position: bottom;
    }

  4. Darn, if only I could edit my previous comments, I wouldn’t have to post so many of them..
    Anyway, I think this technique doesn’t work in Internet Explorer 7.0 :( First I tried mine and it got stuck and then I tested yours. Apparently, the image stays in the active state after the first click and doesn’t change on hovering.

  5. Great technique that I use on my own site for the navigation.

    I think this is the best job I’ve seen explaining it though. Bravo!

  6. designfollow says:

    thanks for this great tutorial.

  7. paul says:

    I can’t see the first image and the sprite image in Chrome

  8. Tom Kenny says:

    Paul – Image problem should now be fixed.

  9. Dennis says:

    Tom,

    I can get one button to work, but when I use (2) buttons on the same page, it wants to display two of the same button. I’m sure it is a coding problem as I’m new to CSS.

    I place this into the style sheet .

    a.button {
    background: url(/button.png) no-repeat 0 0;
    width: 270px;
    height: 84px;
    display: block;
    text-indent: -9999px;
    }
    a.button:hover { background-position: 0 -86px; }

    a.button2 {
    background: url(/button2.png) no-repeat 0 0;
    width: 270px;
    height: 84px;
    display: block;
    text-indent: -9999px;
    }

    a.button2:hover { background-position: 0 -86px; }

    I place this into the blog post

    Button

    Button

    Any help would be appreciated!

    • Tom Kenny says:

      Dennis, make sure you have assigned classes that match up with your CSS. For example any CSS properties assigned to a.button will only work on a link that contains class=”button”. See the code below:

      <a class="button" href="#">Your link here</a>
      <a class="button2" href="#">Your link here</a>

  10. Dennis says:

    thanks! works now.
    you can see the buttons here . bottom of the page
    http://www.crushandshred.com/glass-bottle-crusher-for-a-bar

  11. Tim Lombardo says:

    Great tutorial, thanks for sharing. Just wondering how a person would use this same method but have the active state remain in active state once the button is clicked. I’m using this technique for a nav menu and would like the state to be active once a person is on that page.

    Thanks again!!

  12. Tim Lombardo says:

    Hah..figured out a simple solution, just created another class that is just the active state and will use that on the corresponding page. This is my first day coding with css, quite the newb, I’m sure I’ll be reading more and more of your content as I go on!

  13. Karlotta says:

    Actually, I would love to know how to keep the active state on as well. Or even how it’s called, so I can search for it elsewhere?

    I’ve got a page with 6 buttons that send content into an iframe, and I’d like that button to remain lit up as long as the content is there (therefore, until another button is pressed!)

    Any idea how to do this? Or how it’s called? Because I don’t know any other word than “active” to describe this, I can’t find it anywhere…

    Million thanks if you can help me!

  14. Celebrity says:

    Nice work, ty for the tut, will test it today.

  15. netbaazigar says:

    Loved the post.
    I am taking the liberty of adding a reference to your article on my CSS aggregator site. Do let me know if you are ok with this.

  16. James says:

    This works with buttons that are part of an but what about buttons?

  17. wie ajuz says:

    i like this efect, thanks for the tutorial

  18. Meredith says:

    I’m new to this. So how does the HTML code go? I’ve got 2 buttons to do this with that will appear on the same page. What does the HTML code look like for each button?

  19. Renato ( Perú ) says:

    Sorry, man.
    I speak spanish, but i’ll try to write clearly my question.
    How I can add a link to my button?
    My button is this :

    .down {
    background: url(http://a.imageshack.us/img839/2235/downv.png) no-repeat 0 0;
    width: 67px;
    height: 19px;
    display: block;
    text-indent: -9999px;
    }

    div.down:hover { background-position: 0 -19px; }

    div.down:active { background-position: 0 -38px; }

    Well, now I have another question.
    How I can make my button is on top of another image? I hope my English classes have helped me to improve my English hahaha greetings!

Become Part of the Discussion

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.