25
Aug
2008
30

How to Add Drop Shadows to Menus or Windows with CSS

menu with drop shadow

As a followup to my previous post on adding shadows for greater usability, here’s one quick way to implement such shadows using only CSS. Note: I will assume you are fairly familiar with CSS layouts and Photoshop for this tutorial.

The Method

There are different ways of tackling the problem of adding shadows to menus and windows with CSS — this is just my take on it. It’s not the most straightforward task and you may be able to find more elegant solutions by experimenting yourself.

The core thinking behind my method is to add the shadow (a transparent PNG image) as a background to the menu div. We’ll need to slice up the shadow image into separate parts if we want the div to scale.

I’m going to make a fixed width menu (which scales vertically when there are more links), so I’ll split up the shadow into 3 images. If you want the div to scale both horizontally and vertically, you’ll need at least 4 (that’s where it gets much more complex, so I advise going with fixed width unless its really not possible).

Images

I’m going to cut the shadow into 3 slices. Create the image in Photoshop (or your favorite graphics design tool) which is the same width as the menu you want, then add a drop shadow layer style to it. Settings close to these will give you a nice soft shadow:

photoshop shadow settings

Flatten the image and slice it into three. You want get the whole top of the shadow, spanning the whole width and a little into the menu — this is so you get the whole of the shadow edge, as it has a large curve radius. Also get the bottom and a middle section (just 1 pixel in height would do for the middle as it will be repeated vertically). Note that I am cutting the menu surface itself as well as the shadow.

slicing the shadow

Make sure to save the resulting slices on a transparent background. Here’s the images I cut up (the shadow is fairly difficult to see on those transparency squares, but it’s there):

the shadow images

The Markup

I’m using a pop up menu as an example, so I’ve drafted up some simple markup for this purpose. Obviously your menu would probably be more advanced and functional, but I’m focusing more on the shadow here and not the menu. Here’s the markup:

<div id="menu">
  <ul id="menu_list">
    <li>Lorem</li>
    <li>Ipsum</li>
    <li>Dolor</li>
    <li>Sit</li>
    <li>Amet</li>
  </ul>
  <div id="menu_bottom"></div>
</div>

Pretty standard markup. We’ve got the main menu div, then a nested unordered list with a bunch of list items. Each list item would contain an anchor if this was a real navigation menu. The last item is the “menu_bottom” div. This is needed to display the bottom portion of the shadow — I’ll get to that in a second, but now let’s take a look at the CSS.

The CSS

Here’s the CSS I used to style the markup above with the shadow images I’ve created earlier:

#menu {
  padding-top: 26px;
  background: url(shadow_top.png) no-repeat;
  width: 164px;
}
#menu_list {
  padding: 0 0 6px 0;
  margin: 0;
  list-style: none;
  background: url(shadow_middle.png) repeat-y;
}
#menu_list li {
  padding: 2px 35px;
}
#menu_bottom {
  height: 26px;
  background: url(shadow_bottom.png) no-repeat;
}

Pretty simple. Let’s examine each element in detail:

First, we add a padding to the “menu” div. This padding is the same height as the top shadow image. This padding allows us to apply the shadow as the background so it will show up at the top of the div. Also, we give this div a width the same size as our shadow image width.

Second, we need to style the unordered list. Get rid of any default padding, margins and styles it may have (I’ve added a little padding at the bottom for aesthetics) and apply the middle shadow image as the background with a y-axis repeat.

Third, add a little padding to the list items so they have a little whitespace between them and the edges of the menu div.

Finally we need a way to add the bottom shadow. We’ve used up the “menu” div and the “menu_list” items, which is why I’ve added another div at the bottom called “menu_bottom”. Just give it the same height as the bottom shadow image and set that as the background.

That’s it — all done. The result will look like this:

menu with drop shadow

Legacy Support

But wait! What about IE6 and older browsers? They don’t support alpha transparency so the shadow images will look pretty bad.

No problem — we can add IE6 (or older) specific CSS code to provide an alternative to the PNG shadow images. I’m going to make a set of GIF images for IE6 with a solid 1 pixel border, instead of the soft shadow. To tell IE6 to use those images instead of the PNGs add the following code in the markup head section under the previous CSS code/include:

<!--[if lt IE 7]>
  <style type=”text/css” media=”screen”>
    #menu {
      background: url(shadow_top.gif) no-repeat;
    }
    #menu_list {
      background: url(shadow_middle.gif) repeat-y;
    }
    #menu_bottom {
      background: url(shadow_bottom.gif) no-repeat;
    }
  </style>
<![endif]–>

And yes, you can of course include an IE6 specific stylesheet between those tags instead of the style code directly, which I recommend. This will give us the following results when we view the same page in IE6:

menu in IE6

And there you have it. Beautiful shadows implemented with W3C valid markup and CSS, that also degrade gracefully for older browsers. If you like, you can download the source files here.

Have any thoughts about this or a better way you know of to add shadows to menus and windows? Post a comment.

Share/Save/Bookmark

Enjoyed reading this post?
Grab the RSS feed here and get all new posts delivered straight to you.

30 Comments:

  1. MikeWhoBikes

    Thanks for a great follow up post, Dmitry. I think I’m going to have to give this a try.

  2. Jin

    Nice article Dmitry.

    I’d like to note that you can use iepngfix for ie6 to display alpha transparency. also, you can use filter: glow to make a ie specific glow shadow effect as well. (there’s also the shadow filter for drop shadow effect).

    thanks.

  3. Dmitry

    Jin: Thanks for the tips — I’ve never used the glow filter before, very interesting.

    The PNG transparency fix for IE only works on images in the markup though and not CSS image backgrounds. What’s more, it can cause some positioning issues, so I prefer not using it myself — but yeah, if you really wanted to you could hack together a solution for IE6 as well, but honestly, I think that’s too much bother :)

  4. Jin

    Dmitry: the early iepngfix scripts people wrote only supported img src not background-image in css, and often they were a bit buggy as you mentioned. there are a lot more advanced ones written now, also more compact.

    http://labs.unitinteractive.com/unitpngfix.php

    this one is very good.

    but whether we should continue to support IE6 is another story :)

  5. Dmitry

    Jin: On their site it says it will stretch the background image to the size of the div instead of repeating it if it uses the background repeat property — so I don’t think it’s quite there yet — however I think it would work OK for this problem. Thanks for the link.

  6. Simon

    Thanks for the post. I’ll be using this. Is it possible to just create the GIF images in the first place and avoid PNG altogether? This would therefore work well on IE6

    As much as I love PNG, I make it a point to avoid browser-specific styling (unless it’s something like a CSS3 special command).

  7. will

    Nice article for sure. The title is a little misleading, however. Maybe it should be “How to Add Drop Shadows to Menus or Windows with CSS and a PNG Image”.

    I must admit, I got excited thinking it was possible to do this without the image.

  8. acms

    I was thinking the same think Will, anyway good technique for shadows, ill give a try. Thanks for sharing.

  9. Dmitry

    Apologies about the title Will! Tried to make it shorter and I guess ended up with one that’s not 100% clear.

    Something to look forward to would be the CSS3 box-shadow property, which does pretty much what we have above. Some info: http://www.css3.info/preview/box-shadow/

  10. Dmitry

    Simon: GIF images only support two transparency states — completely transparent and opaque (0% transparent), which is what we’ve got in the last screenshot where I implemented the GIFs for IE6.

    This loses the advantages the soft drop shadow gives you that I’ve discussed in my previous post here: http://www.usabilitypost.com/p.....nd-windows

  11. JONxBLAZE

    Great post this is almost the same method I used to layout my blog design. Thanks!

  12. Fernan

    Great tutorial!

  13. Markus Nordin

    Although this is a strict javascript solution, it does get the job done without the use of any CSS hacks and works with IE 5+. In conjunction with a GIF solution for IE people with javascript turned off, this could be an alternative. IE7.js: http://code.google.com/p/ie7-js/

    An even better solution in my mind would be to spice the GIF up with a hard shadow if the design could handle it. Haven’t come across a true pngfix that fixes background images yet, until then we’ll have to fend for ourselves (or tell people to stop using ie6). I’ll be looking into Jins’ recommendation.

    Great tutorial anyway!

  14. Napolux

    Thanks! I was just making a CSS-shadowed template for my blog.

    Your post is very useful!

  15. Swaran Singh

    Hi i think this is very easy and most of us must being knowing about this. it would be great if you can provide us with a css where we can apply shadow to a module directly instead of cropping a image into three parts and then doing it. by the way this would have also been useful to many others. good Job :)

  16. Search Engine Optimization

    I cant wait to try this. Great Post.

  17. Jan

    Is it possible to implement this technic in Wordpress 2.6 without any modifications to the menu output? Wordpress generates only

      and
    • … i see no way to style it your way, because there is simply no additional or
      to implement the 3 graphic slices. The only way would be to make one large background shadow and implment it as the
        background with position bottom. If anybody knows a suitable simple solution for wordpress please write an article about it and post the link somewhere here in the comments section! Thanks in advance!

  18. Dmitry

    Jan: I’m sorry but I don’t have much WordPress theming knowledge — but as far as this method goes then no, it won’t be possible to implement unless you add the additional divs.

    That’s one of the biggest problems of CSS 2.1 — you can’t assign multiple backgrounds to the same div, so you need to have these other divs or other block elements like

      and

      to act as hooks for the other images. CSS 3 will offer multiple backgrounds, borders, shadows etc., but I don’t think we’ll be seeing that soon.

      Regarding your problem — I think it should be possible to wrap the

        items in extra divs in your template files, but as I said above, I don’t really have much WordPress knowledge so don’t know for sure.

  19. pijus

    very good.

  20. Mark

    Pretty good implementation :)

    Pity it doesn’t look so good when there are further levels to the dropdown :(

    Just FYI, the latest alpha version of the twinhelix fix works quite well with background images –> http://www.twinhelix.com/test/

  21. Chris Bolton

    There is an easier IE6 fix. IE6 does not recognize the important declaration in CSS so using the following code would save you having to use a conditional statement:

    #menu {
    padding-top: 26px;
    background: url(shadow_top.png) no-repeat !important;
    background: url(shadow_top.gif) no-repeat;
    width: 164px;
    }

  22. Dmitry

    Thanks for the tip Chris. I prefer not to use hacks inside the main stylesheet and instead separate them into IE specific ones — but this is certainly concise and may work for you.

  23. Tetsuo

    Good tutorial - coming up with drop shadows using CSS is never easy.

    Just a thought - instead of using an empty div for the bottom, which obviously isn’t ideal - would it be possible to instead apply the background (bottom image) on the #menu container, then use a class on the first list element to add in the background for the top image?

    Obviously you would need to tweak the basic CSS a little too, though. It might even be possible to use CSS3 for this to select the first element in the list.

  24. [...] - How to Add Drop Shadows to Menus or Windows with CSS [...]

  25. Poonam

    Hi,

    Nice Tutorial, but you cant escape the clients requirements if he wants to see shadow in IE6. So, with some hacks of IE6 it is possible to show shadow in IE6 also.

    Thanx :)

  26. dora

    Cool info thanks. Here is the easiest way to generate drop shadow: http://www.dropshadowz.net

  27. [...] Dmitry illustrates How to Add Drop Shadows to Menus or Windows with CSS [...]

  28. Antonio Wells

    This is a great post. Thanks!

  29. [...] - How to Add Drop Shadows to Menus or Windows with CSS [...]

  30. Erik Kallevig

    In the spirit of css sprites, you can improve this technique by using only one image: align each of the three graphics side-by-side horizontally in one image, and then access the sections you need by changing the background-position-horizontal css property.

Post your comment

Credits: RSS icon designed by Function.
Powered by WordPress.