Redswish

Carefully crafted banter

CSS Horizontal Menu

I’m big into horizontal menus. I think the majority of the web community are. In my eyes their only pitfall is the general inability to expand past a set width if you wish to add more links in. But who wants to do that, anyway?

I’m aware that there’s a multitude of different ways to create the classic ‘hover-over’ menu. Either with CSS or good old javascript, the way Dreamweaver used to throw it out, and possibly still does. There are several reasons why I choose not to use javascript hover-over effects; a) It’s ugly, just to look at. Little brackets and weird symbols and colons everywhere, b) In some way or another it’s going to want to attack your site’s accessibility, and we just can’t let that happen, c) CSS is just better. In every way. It’s cleaner, easier to apply and moderate and just stays out of the way in it’s little file. With javascript you’d either have to throw plenty of dirty code into your markup, or create another external .js file. Why bother?

Of course CSS isn’t without it’s flaws. Wait – did I just say that? What I meant was CSS is perfect in every way and does everything I want it to. It does, really. The only thing I could ask would be the ability to have the hover-over fade in or rise up to create some nice ‘ajax’ effects. But wait – then we’d be back at javascript, which defies our objective.

Even CSS menus can be achieved in a number of ways, I used to use a method where the original menu button and it’s roll-over button were 2 different images, the 2nd called up by CSS when the mouse hovered over it. I was finding that the browser was having to load the image every time, thus creating a ‘lag’ effect as you hovered over a menu item. Which was insulting.

So I will now embark on explaining how I now go about creating my faithful horizontal menus. For the purpose of this tutorial and to save me time, I’m going with a simple blue bar – 800px x 40px. No glossy effects or 3d optical illusions. A plain blue bar, as you hover over a menu item it’s background will glow a lighter blue. Nice and simple.

I’ve originally designed my menu in [generic image-editing application] aka Photoshop as below. The menu itself will be 800px wide by 40px high. The individual buttons will be 100px wide. So, upon designing the menu as how it will look in general and if one of the links is hovered over, I’ve set to work creating images of the individual links.

CSS Menu 1

I used to create 2 images for each link – 1 for the original button as it will appear on the menu, and 1 for the hover-over. Now instead, I create 1 image that incorporates both, so instead of 40px high it will be 80px high and display the original button above the hover button, like so:

CSS Menu 2

I do this for all the links – so in this case 5 images: Home, Blog, About, News, Contact and named them appropriately (eg. menuhome.png). I’ve created an image of the menu background without the links and I must also create a transparent image. This is where my method may vary from many others. In some cases, your menu links in the HTML file will be simple text links. But I don’t want text, as the CSS ‘background’ image will be providing that. So to replace the standard text in the <a href> anchor, I will create a transparent image the dimensions of the button – 100px x 40px, this button will called ‘menubutton.png’.

CSS Menu 3

On to the code. HTML first. The 5 links will be in a nice semantic <div>, organised by an unordered list <ul>. Here goes:

<div id=”menu”>

<ul>

<li id=”home”><a href=”/” title=”Home”><img src=”/images/menubutton.png” alt=”Home” /></a></li>

<li id=”blog”><a href=”/blog” title=”Blog”><img src=”/images/menubutton.png” alt=”Blog” /></a></li>

<li id=”about”><a href=”/about” title=”About”><img src=”/images/menubutton.png” alt=”About” /></a></li>

<li id=”news”><a href=”/news” title=”News”><img src=”/images/menubutton.png” alt=”News” /></a></li>

<li id=”contact”><a href=”/contact” title=”Contact”><img src=”/images/menubutton.png” alt=”Contact” /></a></li>

</ul>

</div>

As you can see, I’ve given each <li> an id. This is so each button can be individualised in the CSS. Now on to the CSS, which I’ll break down as we go along.

#menu {
width: 800px;
height: 40px;
float: left;
display: inline;
background: url(images/menubackground.png) no-repeat;
}

*This lays out the menu bar, specifying it’s height, width, position and background.

#menu ul li {
width: 100px;
height: 40px;
float: left;
display: inline;
background-position: top;
}

*This styles the general list items in the menu. Height, width and ensuring that the background images are originally at the top. Now we style the individual items with their own background image:

#menu ul li#home {
background: url(images/menuhome.png) no-repeat;
}

*That’s it for the standard button! Simple. Now we apply it’s hover-over:

#menu ul li#home:hover {
background-position: bottom;
}

*All we’re doing is pushing the background image up to show it’s bottom half. Because the image is already loaded, there’s no waiting, it’s a nice quick transition.

That’s it for the CSS. There’s no need to style the ‘ul li a’ because it’s just a transparent image – all the design is in the background image you’ve already created.

This isn’t always necessary. If you wish to use standard text links you can use the exact method as above, but with adding text styles as well. The reason I use this method is because it gives me the ability to create really attractive buttons that couldn’t be achieved with standard text and CSS alone.

Anything I’ve done wrong, if you don’t quite understand how I’ve explained this method or you’d like to correct me and provide a better way – get in touch or leave a comment. I welcome constructive criticism!

Comments & Opinion

19 Responses. Have your say.

  1. James, on , said:

    That’s a way I never thought of doing it. It seems a long way round in some aspects but it’s not really. Plus you can get great looking buttons instead of having to do with bad browser font renders.

    I’ll give that a shot.

    Cheers!

  2. M, on , said:

    Had to change the li class reference to a id reference (. to #) to get the buttons to work. Now, however the button list items are not aligned center with it’s background.

  3. admin, on , said:

    Ah yes, I’ve changed that, sorry for the confusion with the id/class, however I’m not sure why it’s not aligned correctly? If anyone else is having the same problems please let me know, thanks!

  4. mm0704, on , said:

    Have also been having problems with this method of doing it.
    Seemed like an excellent way too :o (

  5. Deniz, on , said:

    This is exactly what I am looking for: PS buttons with nice font styles. But I couldn’t worked it. :( All I get is blue horizontal bar, without could you see sth wrong with this code:

    #menu {
    width: 800px;
    height: 40px;
    float: left;
    display: inline;
    background:url(images/menubackground.png) no-repeat;
    }
    #menu ul li {
    width: 100px;
    height: 40px;
    float: left;
    display: inline;
    background-position: top;
    }
    #menu ul li #home {
    background:url(images/menuhome.png) no-repeat;
    }
    #menu ul li #home:hover {
    background-position: bottom;
    }





  6. admin, on , said:

    Hey guys, sorry for messing you around with this tutorial. It’s one of the challenges of web design – problem solving and trial and error.

    I’m building it all again to see where I’ve gone wrong. Chances are it’s probably something ridiculously simple but that’s always the case.

    If you having problems – please leave a message or contact me and I’ll happily help you out individually.

    Thanks

    Nathan

  7. Sam Starling, on , said:

    Hey Nathan, how’re you doing? Nice blog, thought I’d weigh in with my two cents of CSS geekery! Forgive me… This is how I tend to do things, with one big image of every link (home, blog etc.) with its hover state below it.

    #menu {
    width: 800px;
    height: 40px;
    float: left;
    }

    #menu ul li {
    float: left;
    }

    #menu ul li a {
    width: 100px;
    height: 40px;
    float: left;
    /* Make the links bigger, not just the list item */
    }

    #menu ul li a {
    background: url(‘Picture.png’) 0 0;
    }

    #menu ul li a:hover {
    background: url(‘Picture.png’) 0 -30px;
    /* -30px vertical offset, the hover row is 30px below the normal */
    }

    Then you do…

    #menu ul li#blog a {
    width: 100px;
    background: url(Picture.png) 123px 0;
    }

    Meaning that the “blog” item is 123px from the left and 100px wide. Does this sound like jibberish yet?

    You can also remove the images from the links and use text instead so it degrades nicely, then just add text-indent: -10000px; or whatever to #menu ul li a to make it not actually show up. Hope you’re doing well mate!

  8. admin, on , said:

    Mr Starling here is perfectly correct. If you prefer his version I welcome it. It works on very similar principles but instead of the ‘background-position: bottom;’ you specify that the image is pushed however many pixels up (in this case 30 (-30px).

    Sam’s final comments about using the text instead of the ‘menubutton.png’ image hold true – but unless I’m mistaken this means when you hover over the button you will still have to click over where the text link would be as opposed to being able to click anywhere on the image. Try it – I could be wrong!

    I promise to rebuild this entire tutorial to try and figure out where I’ve gone wrong above. If anyone figures it out beforehand – please let me know so everyone else can benefit!

  9. Sam Starling, on , said:

    You’re too right Nathan, the good thing about CSS are the different ways of achieving one thing. Vive Le Difference!

  10. Florian, on , said:

    I like the concept of this idea and will definitely give it a shot!

  11. This is really worth giving a try, and thanks for putting it up!!
    Grt Work!!!

  12. Very nice ;) btw very good tips i will use some of them. Some i did not knew.

  13. Ryan, on , said:

    For those who use Dreamweaver and need an easy way to integrate a pure CSS menu into their website, there’s a new extension called CSS Menu Writer that builds pure CSS multi-level menus. Here’s the link: http://www.webassist.com/professional/products/productdetails.asp?PID=146&WAAID=649

  14. admin, on , said:

    Re: Ryan

    I don’t generally use Dreamweaver so it won’t apply to me, but I’m sure others will find it useful.

    Are the menus valid and accessible though? I’ve been wary of any WYSIWYG editor, when I know if I code everything myself it will almost always be valid and accessible. Although I have toyed with Dreamweaver CS3 and it is very good.

    Thanks for your comments!

  15. Ryan, on , said:

    The extension development was overseen by Eric Meyer, whom I’m sure you’ve heard of if you’ve been around CSS for any length of time. The menu code validates for both CSS and HTML. The menus are simply unordered lists styled with CSS, but the real advantage is the speed at which you can create multi-level menus.

    The interface just aids in making the customizing more “visual” with a live preview of your menu as you make changes. For designers familiar with CSS, they can easily make changes directly in the CSS code. The extension also allows you to save, export and import previously created menus, so you can reuse menus on any number of sites. If you’re comfortable coding cross-browser CSS menus, and are aware of all the different browser quirks, then save your money. But if you want a way to code menus quickly and be able to migrate menus between sites, it’s definitely worth a look.

    Thanks!

  16. Hikari, on , said:

    That’s a nice menu, tnx!

  17. css background examples , Properties , Attribute – - http://css-lessons.ucoz.com/background-css-examples.htm

  18. HI i need your help i really want to create my own website/web page but i dont know how to go about doing it so can you please help me out

  19. admin, on , said:

    I’m sorry Ornekleri but how to build your own website isn’t something I can cover in 5 minutes. It’s worth searching the web for tutorials and getting hold of a couple of books.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>