How To Create Stylish Navigation Buttons With CSS

Most of the time when designing your site navigation you’ll turn to an image to give it that something extra. However images add weight to a web page and make additional http requests leading to longer load times. Ever since I began developing websites, I’ve looked for ways to replace images with code. Today I want to share a simple way to style navigation buttons sans images and using css only.

Note: If you decide not to use the technique below and prefer to use images for your nav buttons I suggest using css sprites. If you’re unfamiliar with css sprites have a look at these posts to learn how to use them.

Final Navigation Bar Preview

Before we begin let’s take a look at where we’re going. Here’s an image of what our final navigation bar will look like as well as an image of how it will look when mousing over one of the buttons.

And here’s a demo of the navigation bar that will open in a new window.



Even without using images the nav bar above has a 3D feel to it and gives the impression that the buttons can being pressed or clicked.

I won’t be going over all the code used to create the navigation bar in this post as I’ve covered most of it before in my simple navigation bar post. What I want to show you today is the part that gives the button the 3D effect, though I’ll provide all the code to create the nav bar at the bottom of this post.

CSS Borders to Give any Element Depth

The trick to the 3D effect, as you can guess from the heading above, is to use css borders to convey a sense of depth from an imaginary light source. There are 3 simple parts to this technique.

  • decide where your light source is
  • give sides where light shines a border a shade or two lighter than the button color
  • give sides that would be in shadows a border a shade or two darker than the button color

Let’s illustrate the three steps above using a grayscale version of our navigation bar to make the color changes easier.



I’ve used #555555 as the color for the grayscale buttons above and we’re assuming our light source is shining from the upper left. That means the top and left sides of the button should appear lighter while the right and bottom sides will be darker.

#555555 is the hexidecimal representation of a medium gray. To make the color darker we want to lower the numbers toward 0 and to make it lighter we want to increase the number toward F. Here’s the border code I used to create the effect.

{code type=css}
border-top:2px solid #777777;
border-right:2px solid #333333;
border-bottom:2px solid #444444;
border-left:2px solid #777777;

I’ve used a 2px border for each side and for the top and left sides used a color of #777777 or two shades lighter than the button color #555555. The right side gets a color two shades darker at #333333 and the bottom I only went one shade darker with #444444.

In practice you might only use a 1px border, but I used 2px here to make the effect more obvious. Also I’ll tend to play around a little with the colors until I get something I like, though I usually start by making all the hex values one or two numbers darker or lighter.

With the rollover button the process is similar except that now the top and left sides will be darker and the right and bottom sides will be lighter. Here I used a color of #999999 for the button itself and then for the borders the code is as follows.

{code type=css}
border-top:2px solid #777777;
border-right:2px solid #aaaaaa;
border-bottom:2px solid #aaaaaa;
border-left:2px solid #777777;

Again it’s the same as before except for the darker and lighter sides being reversed.

Extending the CSS Border Technique

The technique above is very simple, but there’s no reason you can’t extend it some for more creative possibilities. You can try altering the width of the different borders or play around with the colors to make it look like the light has been cast through a filter. Instead of changing all 6 hex digits you could raise or lower only the red or green values while keeping the blue constant.

One thing I’ll sometimes do is not change the top and bottom border colors on the rollover. That will give the impression that when pressed in the button sits at the same level as the surrounding page, instead of feeling slightly depressed from the page as shown here.

This technique is also hardly limited to navigation buttons. You can use it on any element that accepts a css border. You could for example set up a class for all your buy now buttons using this technique and then apply that class wherever you want a buy now button across your site.

Hopefully in the not too distant future when all browsers can handle things like css gradients and border radius you’ll be able to style the button with code only and eliminate the need to ever use an image for a button. For now you can use either as part of progressive enhancement on your site.

Code Used to Create the Navigation Bar

As promised here’s all the code I used to create the navigation bar at the top of the page. The #nav-wrapper code is there just to have a color that shows what’s going on better than the white of the page. It’s presented here, but not necessary.


{code type=html}



{code type=css}
#nav-wrapper {
margin:0 auto;
padding:20px 0;

ul#nav {
font-family: Verdana;
margin:0 auto;
overflow: auto;

ul#nav li {

ul#nav li a {
display: block;
padding:5px 21px;
border-top:2px solid #815444;
border-right:2px solid #3d1000;
border-bottom:2px solid #3d1000;
border-left:2px solid #815444;

ul#nav li a:hover {
border-top:2px solid #815444;
border-right:2px solid #c59888;
border-bottom:2px solid #c59888;
border-left:2px solid #815444;

Any tricks you’ve developed to replace images with code?

« »

Download a free sample from my book, Design Fundamentals.


  1. The navbar looks nice Steven, I keep mine as simple as I can, too, with CSS.

    Quick question though, why is it that when I click the “contact” button in the demo (or hold it down, anyway), a horizontal scrollbar appears below it?

    • Thanks James.

      I’m not sure why you see the horizontal scrollbar, but I’ll guess you’re viewing the demo in some version of IE (if not let me know what browser you are using). It’s probably the width I set on the ul that gets thrown off. It shouldn’t, but that’s my first thought.

      I didn’t check the code in IE, but I will as soon as I get a chance. My guess is if you reduced the left and right padding on the links by a px or increase the overall width of the ul by a few px you wouldn’t see the scrollbar.

      I’m not seeing the scrollbar on any browser on my end.

      • I’m using Firefox v3 (I rarely use IE anymore, if ever).

        The background color also extends a bit too. Maybe it as something to do with how far I’m ‘zoomed in’. The sizes have always seemed normal to me though, so not sure if that’s it.

        • That’s possible about being zoomed in. I set the ul to be a specific width so I could center it on the page. The width doesn’t really need to be there though.

          If the text size increases then the individual widths of the links will add up to more than the set width on the ul.

          I’m not sure why it only happens on the rollover though. And again the width on the ul isn’t necessary.

          Odd though since I don’t see the scrollbar in FF even when zooming.

  2. Nothing happened for me on a rollover, the changes only occurred when I physically clicked on the links, or held down the mouse button.

    I tried zooming in (making it bigger) and did the same thing, and I got a vertical scrollbar, where the “contacts” link moves right underneath the “home” link.

      • Hey Steve,

        I just wanted to let you know, I found out what was causing the scrollbar to appear, it was the overflow property. No idea why though.

        Apparently something was causing the right side of the bar to get bigger as I held down the mouse button on it. (The border perhaps?)

        I didn’t see it interfering with anything in my navbar (on a site I’m working on) so I removed it, and everything works and appears fine.

        • The solution for the horizontal scrollbar that appears below when click the “contact” button in FirFox browser
          by setting overflow: hidden;

  3. Can’t wait to see wide CSS3 and HTML5 support to create much better navigation buttons. There’s plenty of stuff there that can be used without relying on images.

    • Hey Yura. How are you. Been awhile since we chatted.

      I’m looking forward to css3 and html5 adoption too. Of course that will mean we’ll be waiting on IE and who knows how long that will take.

      There’s so much good stuff coming that’s going to open up so many possibilities for designing with code.

  4. Great navbar, nice and simple! I have one question; is there a way to adjust the width of each tab individually, if you don’t want them all to be the same width?



    • Thanks keera.

      You actually don’t need to specify the widths like I did here. What I usually do now is give each link some padding and let the size of the tabs grow and contract to match the text.

      It’s probably about time I updated this post with a new one.

  5. Well written, but I’m sorry – the navigation bar doesn’t look “Stylish”, it looks 1996.
    I think it would be interesting how to make a navigation bar like this with the box-shadow property, without borders.


    • Maybe stylish wasn’t the best choice of words, but I’d hardly say the navigation bar looks like 1996. Do you remember what the web looked like in 1996?

      As far as box-shadow is concerned, I’m pretty sure it won’t work yet in IE. Not that you shouldn’t use it, but then you might want a fallback. What’s described here will work cross browser. I’ll save box-shadow for another post, though I’ve seen plenty of posts already covering how to use it.

    • I think that leaves some of the presentation in the hands of the browsers though, doesn’t it? I don’t think browsers have to present any border style in a specific way.

  6. thanks a lot :)..but am able to create only four buttons in a row..the 5th button appears in the 2nd to correct this..plz help..!

    • You need to adjust the widths in the css, most likely the ones on #nav-wrapper and #nav. The code above limits them to being 465px wide, which can only hold so many buttons. You might have to play around with the width to get exactly what you want.

  7. Cool simple Styles, thank you for this, btw i’m just using 2 property on border, like this for making shaddow stylish on my navigation blog.

    border-right:2px solid #333333;
    border-left:2px solid #777777;

  8. Hi there, thanks for the great tutorial. I am doing a web design course at Uni. I know this is an old thread, but I am wondering if you could tell me how I centre the buttons, they are all to the left. I played around with it slightly and changed the width from 465px to 80em.
    thanks in advance

    • Are you asking about the entire navigation bar and how to center it?

      The way I centered things here was to set a width on #nav-wrapper and then use margin: 0 auto;

      That centers it inside its container, which in my case is the body. It’s possible the container for your navigation isn’t the full width of the page so it might be technically centered in its container, but doesn’t look like it is.

      If you can’t get it working, send me a link to the page in question and I’ll take a quick look.

  9. hi there, i don’t have a live website as its just for a uni assignment. is there another way I can send you the files?

    • You can email them to me. Look for my contact page under the about menu. I might not be able to take a look right away, but if you send me the files I will take a look.

      If you can zip all the files together and send me the zip.

  10. how to resize button by :hover but still everithing to stay on the same pleace? and not to make changes to width only on height?

  11. This look fantastic, thanks for posting.

    What would I use to put a horizontal gap between the buttons? So they appeared as separate buttons, rather than joined buttons.

    • Thanks Ben. If you remove the background color on the wrapper, you should be able to play around with margins and/or paddings to create the gap. It’s been awhile since I wrote this though and today I would likely build the same navigation bar using flexbox.

      I never wrote a specific post to show how to do that. There’s an example in the book I wrote about flexbox if you’re interested.

Leave a Reply

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