Onion Skinned Drop Shadows

A note from the editors: The techniques demonstrated in this tutorial are not for everyone. The design method works its magic by nesting divs that have no semantic or structural value. If that bothers you (and there are good reasons why it might), this is not the tutorial for you. On the other hand, if you wish to create visual effects that expand and contract to fit any object, require no image manipulation, and render the same across all browsers, then “Onion Skinned Drop Shadows” may be just what you’ve been looking for.

Onion skinned drop shadows? Yes, onion skinned. Animators use onion skinning to render what is impossible to see otherwise: a snapshot of motion across time. Now, web designers can use it to render another seeming impossibility: the truly extensible CSS-based dropshadow.

Article Continues Below

Read about onion skinning with div stacks.

Enough Already#section1

Tired of reading technique after technique outlining the many ways to skin this cat? Just consider this a demonstration of the capacity of CSS to surprise. Just when it looks as though the method is clear and the way is defined, one more wandering mind reveals another creative approach. If all you glean from this article is a deeper appreciation for the diversity of solutions CSS affords, then you’ve benefited far more than any one techniquecould deliver. Read on.

What’s different#section2

There are several differences between this technique and those offered previously, both here and elsewhere. Some may find it simpler than others, some more stable; but no matter how you look at it, it is more extensible. With just one set of simple rules, these new drop shadows:

  • Automatically expand and contract to fit any object, without specifying widths.
  • Allow you to modify the shadow depth with no image manipulation.
  • Render the same across all browsers without cutting any corners.

Peeling the onion#section3

Onion skinning refers to a technique in time-based arts of overlaying several frames in a sequence to discern the subtle differences between them. The animator is simply looking through a stack of layers to see one whole motion through a composite of its parts. What is opaque on one layer can be seen through the transparent areas on a layer above it. We can do the same thing with divs. Using CSS, we can stack divs together in concentric fashion, like the layers of an onion, to form a composite of anything we like. Today, we are making drop shadows.

Isometric view of an onion skinned drop shadow:#section4

  Demonstration image used for drop shadow illustration

Three divs, each containing a different shadow image component (illustration), overlay one another to form a composite drop shadow. The markup couldn’t be simpler.  Just wrap your object inside three divs, one inside the other, and give each a class name which corresponds to its role.  Since we’re “wrapping” the object, the classes we’ll assign for demonstration purposes are named wrap1, wrap2, and wrap3 (.wrap1 assigned to the outer, and .wrap3 the innermost div).

The object casting a shadow

The CSS is a bit more complicated — but not much. There are basically three things that the style rules must accomplish for the shadow:

  • Make it show.  Assign each of the three shadow image components (shadow + two corners) to a different layer in the onion skin stack.
  • Make it drop. Create an offset which moves the drop shadow down, and to the right of the object.
  • Make it shrink-to-fit. Force the divs surrounding the object to collapse upon it.

Step one: rendering the shadow#section5

The basic idea is to assign one of the three shadow image components to each of the divs through its corresponding class.  The sequence of which div gets which component is crucial, though.  The purpose for having three image components is to use the two small ones at the top-right and bottom-left positions to mask the clipped edges of the large shadow revealing only soft, rounded edges all around.

In order for one image to mask another, it must reside above it in the z-index. We don’t have to worry so much about indexing the stack, since the nested structure of our divs carry’s an intrinsic stacking order that works for us. We simply assign the class with the shadow to the outermost div at the bottom of the stack. Since the divs inside it will naturally sit on top, we’ll give the classes with the corner images to them.

.wrap1 {
.wrap2 {
.wrap3 {

Once we’ve assigned the right images to the right classes, we need to give them position — background-position, that is.  If we left the rules alone at this point, all we would see is a tiled background of “corner_tr.gif” since it’s sitting highest in the stacking order.  Remember, onion skinning requires transparency in the upper layers so that we can see what’s beneath.  To do this, we’ll cancel the repeating property of all the background images with no-repeat, and position them where they belong to form the composite of our drop shadow.

Common sense tells us that an image named “corner_tr.gif” should reside in a corner — probably the top-right; ditto for “corner_bl.gif” (bottom-left). But, what about the large shadow image? Does it even need position? Yes — more than any other, in fact. If we want our shadow to fall to the bottom-right of whatever object we put it under, we must specify that direction in our .wrap1 rule.  Otherwise, it will automatically fill the div relative to its top-left corner, the opposite of what we need.

The base layer: div.wrap1#section6

The outermost div holds the largest of the three shadow components, which is positioned right bottom.

.wrap1 {
  background:url(shadow.gif) right »
  bottom no-repeat;

The middle layer: div.wrap2#section7

The second div, nested inside the first, masks the clipped lower-left corner of the shadow underneath, giving it a rounded appearance.

.wrap2 {
  background:url(corner_bl.gif) left »
  bottom no-repeat;

The inner layer: div.wrap3#section8

The third div, nested inside the second, takes care of the clipped corner in the upper right.

.wrap3 {
  background:url(corner_tr.gif) right »
  top no-repeat;

Step two: dropping it down#section9

The next step for the CSS is to create the offset that makes the drop shadow drop.  This could not be more simple.  All it takes is a little bit of padding on the right and bottom of the innermost div.  When the padding causes this div to expand away from the object inside it, the two outer divs expand with it.  The result: all three shadow components, positioned along the right and bottom sides of their divs move in tandem, and can now be seen through the gap created by the padding.

.wrap3 {
  padding:0 4px 4px 0;
  background:url(corner_tr.gif) right »
  top no-repeat;

Modifying the offset#section10

Changing the amount offset for your shadows is almost as easy as simply changing the padding values on the .wrap3 rule. We say “almost” because adjusting the padding merely moves the shadow while the corners continue to hug the edges of their containers.  To accurately simulate a shift in offset, you’ll need to tweak the background-position of both corners relative to the padding.

Some would say that it’s good enough to simply adjust the padding, and leave it at that. No sense complicating things to achieve a nuance that is barely discernable for most people anyway. Others would argue that it cheapens the effect to cut corners this way.  If a method will support better aesthetic and technical fidelity, as designers we’re obligated to use it to its full potential. It’s likely that most, however, could go either way.

Judge for yourself.#section11

Flog logoThis image is used below to demonstrate two sets of drop shadow styles.  All instances, in both sets, draw their background-image properties from the same basic set of rules.  In other words, the exact same shadow graphics are used for every instance.  The only difference is the degree of offset.

In the first set of examples, the offset is modified by adjusting only the padding values in the .wrap3 rule, which moves only the shadow — not the corners. In the second set, both the padding and background-position values of the corners are modified so that the entire shadow, corners and all, moves as the offset changes.







Set 1. Padding Only
Flog logo
Flog logo
Flog logo
8 pixels 12 pixels 18 pixels






Set 2. Padding and Background-Position
Flog logo
Flog logo
Flog logo
8 pixels 12 pixels 18 pixels

If you can discern the difference between the two sets, and you prefer set two, then you’ll need to adjust the background-position of your corner images to compensate for the offset in padding. Further, you’ll need to add additional white pixels to the outside edges of your corner images. This allows them to move away from the boundary of the div, without losing their ability to mask the clipped edge of the shadow underneath. Each shadow style is a little different, and as you begin experimenting with offsets, your particular corner white space requirements will become clear.

Step three: making it shrink-to-fit#section12

A little sleight of hand was necessary to coax every browser that was tested into conformity with this requirement, a potential deal-breaker.  But, without this behavior, each and every instance of the shadow style would require the foreknowledge of the object’s width in order to specify the width of the shadow.  Obviously, that wasn’t going to cut it.

Most of the browsers tested would allow the divs to collapse when they received the float property. This would have sufficed, if it weren’t for those of you who use IE5 on the Mac. The mere fact that you exist was reason enough to explore alternatives. Unfortunately, none were found. At least, none that worked universally.

Some research and experimentation eventually revealed that inline-table, an obscure CSS display property value, would be the saving grace of this technique. Right, wrong, or indifferent, this was all that could be found, and it would have to do. So, using the commentedbackslash method to isolate Mac IE5, we give it display:inline-table,and all the rest receive float. So there it is, shrink-to-fit — everything, everywhere, in every browser.

The composite result:#section13

  Demonstration image used for drop shadow illustration

With all three steps in place our CSS looks like this:

.wrap1, .wrap2, .wrap3 {
  /* */display:block;/**/
.wrap1 {
  background:url(shadow.gif) right »
  bottom no-repeat;
.wrap2 {
  background:url(corner_bl.gif) left »
  bottom no-repeat;
.wrap3 {
  padding:0 4px 4px 0;
  background:url(corner_tr.gif) right »
  top no-repeat;

One more rule, for good measure#section14

As in the above example, images will often be used with this technique.  For those occasions, an additional rule which sets a shadowed image’s display property to block will help keep unwanted white space from intruding on a good thing. Just add the following rule to your style sheet:

.wrap3 img {  display:block;  }

Do it yourself#section15

At this point, you may want to browse the drop shadow gallery to get a feel for what is possible with this technique.  We’ve made it easy to download a variety of shadow source images so you can get started.

About the Author

Brian Williams

As Technical Design Director for Wachovia, Brian is slowly contributing to Web Standards ubiquity in big-corporate ways. His design of Calibre.com is the company’s proud foray into standards-based design. Perhaps, someday, he’ll do something with his personal site.

129 Reader Comments

  1. That’s a very interesting technique and deserves further experimentation. It’s a shame about the extra markup, but hey, web-designers are used to making compromises.

    As usual, one has to choose the right tool for any job and, regardless of whether or not the code is semantically or structurally correct, we have one more tool available.

  2. Whislt I have no criticisms of the author or his idea in general and yes I did read the disclaimer, however I still think we are moving in the wrong direction completely by adding this much unnessecary markup simply to accomplish what is nothing more than an ehancement to a site’s visual design.

    It’s time for tag soup all over again, except this time is the DIV tag…

    Sure, this WORKS, but on the scale of importance when it comes to the web standards movement, I’d have to put cleaner, usable code over a simple graphic enhancement.

  3. Great article. I have a question though. Perhaps I’m missing something, but why are we so opposed to non-semantic, non-structural divs. I realize they add weight to the page, and that they’d have to be removed/recoded in the even of a major redesign, but otherwise… AFAIK, unlike tables, they don’t affect assistive devices or software, do they? Also unlike tables, they don’t affect the display of the site sans style-sheet (unless some browsers give them a default margin or padding value, which I don’t think they do). So what’s the fuss? Note that I’m not trying to start a flame-war, or that I’m suggesting the reckless use of divs — I’m only asking a question.

  4. The extra markup seems a bit excessive to me too – however, I can see this technique being extremely useful when used in combination with javascript. Just add a “shadow” class to each image you want to have a drop shadow:

    And then drop in some javascript that crawls the DOM tree and applies the extra div markup to any elements that have the “shadow” class.

    A single

  5. I see Luke’s point about tag soup, and I agree with those who encourage the cleaner-is-better mentality, but relative to a site that uses tables for layout…

    Besides, I honestly only see this technique being used for a photo gallery or something of that nature — pages that are more-likely-than-not generated server-side (ie, no one sniffing around in the HTML trying to make updates). Am I wrong?

  6. Hats off to Brian Williams for a really clever way to add a drop shadow. I still think in most cases the old fashioned PhotoShop way is the easiest, but I have no doubt that there will be times when this technique will be indispensable.

    As for all this bother about standards and tag-soup, wake up and smell the IE 6. While I applaud the efforts of the Web Standards project, CSS isn’t yet what it’s cracked up to be, and until the spec is refined, and the W3C stops talking engineering gibberish to mere mortal web designers, I’m sticking with a mix of tables and CSS.

    After all, clients often want their work done yesterday and even Mr. Zeldman admits that trying to make a site wok in all browsers and validate is a time consuming, frustrating task. And hey, aren’t there enough extremists in the world?

  7. yes, it uses non-semantic markup, a whopping 54 extra characters per drop shadow’d item. would people be the least bit upset if there was some standards compliant script which could accomplish the same thing by only adding 54 characters to the markup? i agree that on the code end of things we should do things as efficiently as humanly possible. but we also have a commitment to the client to give them what they want, and if they want drop shadows and one of the other common methods won’t work for whatever reason, this will work quite well. it also seems pretty darn easy. i wouldn’t go so far as to call this tag soup all over again.

    i think there can be such a thing as visual semantics. and while i don’t think it should take precidence over structural/textual semantics at the cost of page heft, neither should it be ignored. 54 characters is not crossing the line.

    my only problem with this method is you can’t redesign with it by simply changing the style sheet(s). to add drop shadows to something that currently exists, no matter how well it’s marked up structurally, you’ve got to go into each page and add the 2 extra divs. and if later you redesign to remove the dropshadows, while you don’t absolutely have to, it’d be best to go in and remove those 2 extra divs (and probably reclass or ID the 3rd) since they were only there to serve a function that is no longer being used.

    so it’s not perfect. but i have yet to run across a perfect method to do damn near anything when it comes to web desing. and thank god for that. if one perfect method existed for anything, it could easily be programmed into a wysiwyg editor that our most clueless clients could use, and we’d all be out of a job. 😉

  8. On both final-version instances of the .wrap2 class, there’s an error:

    .wrap2 {
    background-image:url(corner_bl.gif) left »
    bottom no-repeat;

    Naturally, that should be background: and not background-image: (anyone else noticed how it was out of place?).

    I’m putting this here because I don’t know whether to send an e-mail to ALA for that or if this is the right place. It’s at least related.

    As a response to the discussion, I would just say: use common sense, when using this technique. If you use it for generic pages with all sorts of content, using 3 redundant styling tags is undesirable. If you’re using it for a photogallery of sorts, leaving 3 redundant styling tags may not be bad at all. In the event of a redesign, you’ll instantly have a ton of freedom to add something nice to the photo’s without having to add in new tags, and in such cases a redundant tag or two that isn’t used isn’t so bad either. People don’t read photogalleries using Lynx or a screenreader.

  9. While it is an interesting technique I have to agree with the other comments above that the addition of extra divs just for the visual effect is troublesome.

    Its not that DIVs create problems for screen readers, or that it add too many bytes, etc. Its added complexity the site itself.

    One of the joys of moving to a pure standards-based design is that make you actual web page source code a lot cleaner and easier to change/manipulate. All the pretty graphics stuff should be in your stylesheet.

    This method re-introduces markup mess into the webpage. Before you may have to sort your way through a mess of nested tables to try and change or fix one small error. I don’t miss those days. Adding nested DIVs is heading us back into that quagmire of obfuscated web page source, and for what reason? A simple visual effect.

    It can be useful I guess, if its server generated or javascript generated then the original source code of the page would remain relatively easy to change/fix, but I think I’d rather go with a purely CSS method of adding a visual effect and leave my markup clean and easy to read.

  10. The 5th version of the shadow’s source image wouldn’t allow for expanded shadow lengths, as-is. Like the other 4 examples, it should be a filled in square, I believe.

    Nifty styling ideas, and I like the increased extensibility.

  11. Some of you even precluded your comments with, “Yes, I read the disclaimer,” but continued to wax standards-zealot on why this is a ‘bad’ or ‘questionable’ approach.

    It’s a clear issue: to a standards-savvy developer, this is obviously something meant only for person sites, experiementation, or extreme situations in which you know that the added page weight is acceptable, and any other developers tackling the project would have knowledge of this method’s implementation.

    No need to spew the same tired concerns. We’re all familiar with them.

    That said, I think it’s an interesting approach, and I am interested in tweaking it myself to be extensible as far as the canvas color is concerned. Currently, this method requires you to ‘hard-design’ your shadow images in correllation with whatever background color they would sit on.

    Nice diagrams as well.

  12. I think this is great method for now, yes there are some nested divs that increase size, but that is acceptable for now. Until something better comes along, this works great.

    What is that something better? Well, I would like to push for in CSS 3 the ability to have more than one background image in an html element. This would solve many problems. I know Douglas Bowman has been pressuring Tantek to consider this in CSS 3 (see http://www.stopdesign.com/log/2004/05/09/blogger.html).
    It certainly would allow us to have cleaner html.

  13. It seems like the general consensus is that this method is great – except for the extra markup. So I messed around a bit to see if the same effect could be produced with no extra markup, and only a bit of javascript:


    There’s not much to it – just add class=”shadow” to any element that you’d like to have a drop shadow. Then call dropShadows.js in the head of the page.

    As far as I can tell, it works in IE6, Safari, IE5/Mac, and Firefox. I haven’t tested it thoroughly, and I’m sure some of the javascript gurus around here could poke holes in my code, but it’s a start.

  14. I use the multiple nested divs trick often to place more than one background element into a single presentation elements. For example rounding the four corners of a presentation window.


    Your Content

    I haven’t tried this technique with shadows though and will certainly try. The previous ALA methods I just couldn’t get working across IE/Mozilla as other folks have.

    I know there are folks that don’t appreciate that DIVs could be considered meaningful structural elements, but I do and consider them very handy for surrounding every presentation element in the markup so that each element is contained in it’s own comfortable DIV sections. It’s easy on the eyes and if you apply IDs to the divs to work the presentation beneath them then it makes the CSS and the markup more reflective of each other structurally.

    Just some thoughts, and really appreciate the consistantly useful and coherent articles here.

  15. Wonderful article and follow-ups, I am very interested in employing this technique in future designs.
    The javascript option seems like a great idea and a good alternative to the extra markup.

    Thanks again!

  16. And I thought I had cornered the Drop Shadow market! If it hadn’t been for those meddling kids and their dog, I would have made it, too!

    But anyway, great work! Two minor notes:

    – You can avoid having to use classes for the inner divs by using descendant selectors like:
    .shadow div div {…

    – If you want to add a frame/border to the image (like the previous techniques used) you’ll need to add another div around the image 😉

  17. I am pretty new to css, and have been diving head first into learning it. As a flash/php programmer, I give huge credit to those of you who are using it well, it’s a tricky art no doubt. My question is this… I’m trying to place the image wrapped in divs inside of a TD, and center align it… I’m having no luck trying to do so… nothing I do stops it from aligning to the left ( I assume the float is forcing this) …
    Sorry if this is newbie question… and thanks for any help in advance.

  18. Float the surrounding div left and apply these styles to the img (or any block):

  19. http://www.contentisdead.com/gallery/
    I don’t see how that would work… not sure what I’m missing… I have it setup just as in the example.. 3 divs..
    surrounding those divs in my page is a TD.. and I want to center the whole 3 div block..
    What surrounding div are you saying to float left? and would that not produce the same results, as the outer of the 3 divs is float left…

  20. michael –

    i think just getting rid of the float: left on wrap1 should take care of your problem.

  21. The problem with this is that 1) the size of the box is constrained by the height and width of shadow.gif, and 2) since shadows don’t run-length-encode well, shadow.gif becomes a 10- or 20-kilobyte file even if the box isn’t large.

    So let’s add one more div, and rather than drawing the sides with one big square GIF, have little repeating GIFs draw the right side and the bottom.

    Now the box can resize to any width and height, and the total aggregate size of the GIFs is about 2K.

    I’ll leave the HTML and CSS as an exercise for the reader – it’s pretty obvious.

  22. Good work, just started on my own JS for that, the only thing you might want to do is to cloneNode() the image instead of creating a new one. That way you can keep all the image settings like alt and title.

  23. Thought: imagining every browser supports CSS3 to its fullest, could the same thing be done with ::before and ::after? (note: we can’t use the CSS2 version, :before and :after, as you can’t set display values on those).

  24. It’ll also be good to have world peace. And ice cream! And that is as far away in the future. Well, not the ice cream.

    Sergio is right, the first thing to ditch is the classes by using contextual selectors.

  25. I may be wrong, but I think I noticed a typo in the paragraph which starts, “Some research and experimentation eventually revealed…”

    “So, using the commented backslash method to isolate Mac IE5, we give it display:inline-table, and all the rest receive float.” Did you mean to say “block” here instead of “float”? That what is shown later in the code:

    .wrap1, .wrap2, .wrap3 {
    /* */display:block;/**/

  26. Thanks, Chris! I took your advice and used cloneNode instead of creating a whole new img element. In retrospect, it makes a lot more sense.

    Simon Willison put together a getElementsBySelector script a while back that I’m thinking might be useful here…


    Since it allows the use of css selectors to choose elements, there would be need to add class=”shadow” to each image. Complete separation of structure and presentation…assuming it works, of course.

  27. Insomni, you’re absolutely right. It should be written just as you’ve suggested: “block” instead of “float”. I’m glad you caught that.
    I had a great time documenting this technique, but an even better time learning from all the great suggestions, and taking my medicine from the semantic purists – I’m glad you’re out there. Although, I still believe very strongly that this technique has its place. I began working on it while developing a retrofit for the shadowed content boxes at http://www.wachovia.com. They occur in many different configurations throughout the site, and I needed something lightweight, flexible, and reusable to work for all of them. This was the best solution, in my opinion.
    While some insist that it constitutes a step in the wrong direction, I think it simply gives design a little more room to breathe. Ah…fresh air!

  28. If shadowed image is over 500 pixels width (or height) there is an ugly gap in the shadow…

  29. smee –
    I considered 500px large enough for the purposes of this demonstration – overkill, in fact.

    I encourage you to produce your own shadow graphics in whatever dimensions you think are necessary. Besides, it’s much more gratifying to use your own graphics. Take control, and do something original with it. Enjoy.

  30. I like Zac’s idea a LOT. The beauty of CSS (to me anyway) is the separation of Content and Presentation. This would allow a CSS-generated -presentation- method to remain abstracted. Perhaps even expanded to other concepts. Nice insight.

  31. Zac > I agree, javascript would be much more preferable. I wouldn’t go as far as adding a class to each image though, not for a gallery anyway. I’d put my gallery images in a div with an ID of gallery, then use the DOM to apply the effect to all images within that div.

    Much more effecient than physically adding all of those DIVs. And nobody would lose out if they have javascript disabled.

    In fact, the idea of using this effect but with javascript is quite appealing.

  32. “Some of you even precluded your comments with, “Yes, I read the disclaimer,” but continued to wax standards-zealot on why this is a ‘bad’ or ‘questionable’ approach.”

    Well of course, isn’t that the purpose of discussion?

  33. Re: :BefTer Drop Shadow by Janos horvath

    That’s the best idea yet! About as simple as you can get it.

    Re: Losing the divs by David House
    “Thought: imagining every browser supports CSS3 to its fullest, could the same thing be done with ::before and ::after? (note: we can’t use the CSS2 version, :before and :after, as you can’t set display values on those).”

    Not sure what you mean, but isn’t Janos’s example what you refer to?

  34. Luke, good point…I totally agree. If you’re going to the trouble of using javascript to reduce markup, you might as well go all the way. With that in mind, I tried putting together a little script that does what you suggested, and relies on css selectors rather than class names (Simon Willison’s getElementsBySelector script was a huge help):


    I haven’t done extensive browser testing, but it should work in most browsers that support the DOM, and fail quietly in browsers that don’t. IE5/Mac seems to have a little issue with placement of the images after shadows are applied. They shift a bit – probably something to do with dynamically modifying their dimensions (a more competent javascripter than myself could probably figure out the problem, but I don’t have a clue).

    As far as I can see, the only significant drawback to this method is that the images are repositioned (by the javascript) to allow room for the shadows _after_ the page loads. It’s a little bit unsettling, especially on a slower connection (I’m typing this from a dial-up modem, and the effect is jarring). I don’t think there’s a solution to this… except maybe to apply extra padding or margins to the pre-shadowed images to make their dimensions equal to those of the shadowed images. That would eliminate any post-load shifting, but the css would end up being just a bit more complex. Not a huge deal, but is there a simpler method? (although when it comes to css…is any of this stuff really simple?)

  35. …is it just me that can’t make head-nor-tail of the paragraph headed “Modifying the offset”? If I want to offset by, say, 100 pixels, I simply change the wrap3 padding rule to

    padding: 0 100px 100px 0;

    but maybe I want to “tweak” the background-position, or maybe not, in some unspecified manner. Huh?

    I’ve tried looking at the source, but I’m not much the wiser. I’m guessing it’s something to do with the (also unspecified) size of the corner images, but I’m not sure what. I really shouldn’t have to do this much reverse engineering on a tutorial article.

  36. I dont mind adding three extra DIVs to enhance the sites visual attraction. I dont mind using javascript or even flash to achieve the same results. What I do think, is that this technique is a poor and ineffective alternative to the “real” thing – a custom made image with the drop shadow integrated. If not made in photoshop – a php/gd function would make this procedure easy, effective and dynamic.

    Css in all its glory, but I think it should be avoided in situations where other techniques are superior. To me, using css to create dynamic drop shadows is the same mistake as using tables and font tags where css would be the best way to go.

  37. David – I think you raise a good point…custom-made images with the drop shadows integrated can be the best way to go sometimes. They’re definitely the easiest and most reliable.

    But some situations might require a bit more flexibility. The new redesign of Blogger is the first example that comes to mind. Suppose a template designer wants all user-submitted photos that occur in weblog posts to have a drop shadow. The user can’t be expected to apply his/her own drop shadows, so there are two options:

    1. use a server-side process to generate drop shadows on images when they’re uploaded
    2. use css to apply drop shadows (as in this article)

    Having the server generate drop shadows is a solid way to go, but what happens when the user decides to switch weblog templates? One single drop shadow style may not be applicable to all templates. Template authors will probably want to have different drop shadow styles (or no shadow at all). So hardwiring the drop shadow directly to the image isn’t a reasonable option.

    (There’s also the possibility that a user is linking to an off-site image that the server has no control over. In that situation, css drop shadowing is the only method that works.)

    Another example… drop shadowed images may make sense when viewed in the context of a styled web page – but not necessarily in an RSS reader.

    My point is that drop shadows (and other related types of ornamentation) aren’t really image content – they’re presentational, and since their appearance depends on the context in which they’re found, it doesn’t always make sense to attach them permanently to images. It all depends on the specific situation, I guess.

  38. David > I’m interested as to why you say it is better to do the drop downs in Photoshop. Is it purely because the drop downs will look better?

    Delving in to semantics one more, you have to ask yourself, is the drop shadow an essential part of the image or is it purely a presentational effect…a nice little bell (with whistle) that you’ve added to embellish the images display? Because if this is the case, then I do not believe the drop shadow should be part of the image. A photo of my family should just be that…a photo of my family…leaving drop shadows out gives me the option of using the same photo in different situations. With a nice CSS drop shadow on my webpage. Without one when I paste it into a Word document etc.

    So now we are on to the semantics of an image…dear oh dear. 😀

  39. I totally agree about the drop shadow effect not being a part of the image content. When I said (typed) integrated I didnt necessary mean that the effect should be merged with the image. Now, in contrary to zacs 2 different options, I would probably go for a combination of the two:

    step 1. Have a server-side script to create the drop shadow image.

    step 2. use css to present the drop shadow together with the image.

    step 3. trash the drop shadow image file (optional, depending on site size etc.)

    I think this would be much more reliable and effective than to use css to “stretch” the drop shadow dynamically. It would aslo be more flexible for the administrators, as they could go in detail and choose different colors, x/y cordinates and blurriness of the shadow etc.

    I mean, if you would want the same flexibility using css, you would have to create 10.000 different shadow templates for different backgrounds, styles, colors etc. It just doesnt feel right.

    All in all, this css solution is nice and interesting, but I really dont think its the right way to go, since there are much more powerful tools out there. I would use them instead.

  40. …surely some variation on this Onion Skinning technique is fine? From what I can see, the only thing holding back the flexibility of this technique is IE’s lack of PNG transparency support, meaning you would need to create a new image for different background colors. Now if only PNG transparency was supported, you would just need one greyscale drop shadow image for all of your sites.

    >there are much more powerful tools out there

    Could you elaborate a bit more on this?

  41. Zac, fabulous solution. I have implemented your technique on our hospital Web site and it works beautifully. I decided to use it on our “Find a physician” section of the site for the photos of the doctors. Since the physician information is served through a third-party and then “scraped” into our site template I have no control over the images. What I am able to do is add a class to the pictures (physphoto) and then using your JS technique apply the drop shadow effect without having to worry about the many div layers.

    I also took your technique a step further and set the shadowStyle as a variable that is passed to the JS function:
    function applyDropShadows(cssSelector,shadowStyle)
    Then where you create the wrapper divs I set the wrap1 class to the shadow style:
    wrap1.className = shadowStyle;

    The onload function now calls:

    This enables me to use an infinite number of shadow styles (should I choose) throughout the site by simply altering the dropshadow.css file.

    More at http://www.tastypopsicle.com/dropshadow/

  42. To be more specific about more powerful techniques, I would probably make a gd class for php, that creates a custom drop-shadow depending on the administrators preferences and the image dimensions. But Im sure there are a lot more and maybe even better image creation techniques out there.

    I tend to use css to present graphics. I use languages like gd/php to create graphics.

    Im not saying that this onion skin technique is bad for your heart, it does bring up some interesting ways of dealing with dynamic image creation, and I like the caching/bandwidth-saving feature of css. I still wouldnt use css this “hacky” way (Im referring to the three extra DIVs) to “create” an image, but maybe Im just being old-fashioned…

  43. in spanish we have a saying…”siempre le buscan cinco patas al gato” translated it means: they are always looking for a fifth leg on the cat….what the heck does that have to do with this!?

    what was wrong with creating an image that already has the shadow incorporated!!?

    if you know what you are doing, if you have the training to do it correctly, you don’t need to recode your head off to get it right. it was right all along!! don’t look any further, the cat has four legs…period!

    does anyone remember: “k.i.s.s” – keeping it simple stupid.

  44. An image could be a token of visual information, if it is a photo, artwork, downtown parking map, etc.
    Or it could be a part of the presentation, if it’s a rounded corner, or background tile.
    I would say that the regular rules of separation of content and presentation apply, and drop shadow is nothing more, than a presentation-level element.
    Technically, a single image with drop shadow is all you have to have to achieve the desired effect. Takes one tag, duh.
    Practically, if you are making a thumbnail page for the web gallery, it’s a pain, unless you automate the process, using whatever means you have, starting from the Photoshop actions on your desktop, and up to the server-side image manipulation scripts, which, in turn, might bring in the bandwidth issue.
    In some cases you are way better off with client-side scripting, and this is what this technique is for.
    It’s all about a right tool for the right task, that’s all.
    The more, the better.

  45. In reference to Zac (wasielewski.org) and Ed Knittel (tastypopsicle.com)

    With the javascript suggestions brought forth, it seems like we’re getting closer to how I’d actually want to use this in real life, but not close enough.

    I would want to only apply a dropshadow to images to which I apply class=”dropshadow”. All other images I would want to be left alone (like a company logo, or my “powered by movable type” banner). USing Ed Knittel’s code, I could modify the style sheet to say “leave these images alone”, but the javascript is still applying divs to these images, no matter what my style sheet says. Ideally, I would want the javascript to only run on images to which I’ve specified it to do so.

    Even with Ed Knittel’s more flexible approach, isn’t the javascript still applying divs to all images on the page, even the ones I want left alone? Wouldn’t the client browser doing more work than it should have to?

    This makes the original method proposed by Brian Williams, in which I manually type out div-div-div around my images, more useful to me. But could the javascripters perhaps offer a modified example of their techniques that only apply the javascript when a certain class is specified?

    In answer to KISS-man:
    This technique is perfect for a moblog gallery. Who wants to bother opening photoshop when all you want to do is upload a pic?

  46. I’m not comfortable enough with the nuances of CSS to be a purist, so the extra markup isn’t that huge of a deal to me. I don’t care for upper left illuminated shadows myself (I like the Mac OS X-style upper-centre illumination) but I can see where adding another div would take care of the scaling problems.

    Now, if only there were decent PNG support in Internet Explorer, so Web designers wouldn’t have to be limited to GIFs to display ‘transparency.’

  47. “Why buy the cow, when you can get the milk for free.”

    In other words, KISS-man, you’re deluding yourself if you think tediously manipulating the shadow properties of each and every drop-shadowed image in Photoshop is “keeping it simple”, stupid. You’re buying the cow!

  48. Tony, good question. What you’re requesting is possible, and only requires a slight modification.

    At the beginning of my script (dropShadows.js), you’ll see a few lines that look something like this:

    window.onload = function(){

    The ‘img’ text inside the applyDropShadows() parentheses is what’s important here. It’s a simple css selector (in hindsight, i realize this is a bit ambiguous, because it looks as if it may simply be referring to tags). In any case, insert any css selector in place of the ‘img’ text. So if you want to apply shadows to all images that have class=”dropshadow”, then do this:

    window.onload = function(){

    You can modify it to your heart’s content – if you want drop shadows on all images that are inside

    , then you’d do this:

    window.onload = function(){
    applyDropShadows(‘div#photogallery img’);

    And so on. So you can put classes specifically on your images, or use combinations of css selectors to get at them. Whatever suits you best. Feel free to get in touch with me if you have any questions. I hope that helps!

    Ed – I just saw your modified script – very nice! I hadn’t even considered the need for multiple drop shadow styles, but it’s a great technique you came up with. It can’t get much more flexible than that (…or can it?).

  49. Zac, thanks but you came up with the technique I just made it more flexible. (Un)fortunately, I don’t think the technique can get much more flexible. Well, I take that back. All of the images get float:left and so this technique does not work for images that I had float:right for the press releases on the hospital website. The shadow jutted out to the left. I did get it to work for an image that I had centered by wrapping a div around it to center it (by setting the width of the div and then adding margin:auto 0;). A technique like this could be achieved by passing style variables to through the JS but that isn’t as necessary for me at this time.

  50. All the extra markup required in the HTML makes this a really bad way to go for adding shadows. However, CSS3 includes specs for a new form of generated content, one that contains the element it is generated by – in other words, generated wrappers. You can make as many as you want on one item, so it would be perfect for this technique, since you could do it all for the stylesheet. Unfortunately CSS3 support in all major browsers is a long way off, and hopefully by then you will be able to give shadows to block elements with a new property anyways (like text-shadow, but for blocks).

  51. First, thanks to all who contribute to this web site and share their expertize & solutions willingly and freely. I scuttled development aspirations when dotcom went south last decade. For someone getting back into it on a working basis sites like these are fantastic for ascending the learning curve.

    Ive come to realize that this is a site primarily for enthusiasts, not necessarily lunch-bucket nuts & bolts guys like me. Enthusiasts tend to get deep and mystic over what appears to be trivial. Because, for enthusiasts, this is a hobby, not a profession bound by deadlines, budgets and other limitations.

    I realized this as I eagerly jumped in with both feet to learn standards. I recognize, in myself, a certain pride knowing I am creating something better according to these standards, and not merely hacking my way through. I seems more professional.

    However, discouragement set in due to the time necessary to due something one would zip through with tables. This I accepted as part of the learning process. However, what I do not accept is the increasing acceptance of hacks in order to achieve standards. I realize I am not the only one aware of this irony. For a working professional, using hacks to fix a broken standard is no different than using tables for positioning. But for an enthusiast, a purest, a hobbiest, this is a huge difference.

    I suggest that this web site recognize its identity as primarily a site for enthusiasts (like a garage where individuals meet to soup up their street machines with street-illegal parts). To suggest, as it currently does, that it is a site for standards is obviously misleading (for reasons mentioned). Increasingly, it will become known where to locate a certain hack to fix css standards – in other words, a site for hacks. There is nothing wrong with this if one is an enthusiast. But it should not be confused with the css standards as originally intended.

  52. I definitely see your point, and, in most aspects, I agree with you wholeheartedly. Yes, it’s frustrating, that support for standards is not yet where we would like it to be. Yes, it’s ironic, that sometimes it takes a hack to make things work as they are supposed to, and it’s just infuriating, that nobody, but a little group of enthusiasts, seems to realize the importance of standard-based web design.
    Yes, they are enthusiasts, may be hobbyists, purists, sometimes even called zealots and diehards, but look at what they actually do: they create, and explore, take things apart, and put them back together, share their ideas and experience, and feed on each other techniques, tricks, and hacks. All that for what? For the sake of the obscure idea of making the web a better place. And guess what? It’s happening, may be, slower, than desired, but it’s happening.
    There will always be web designers, whose tool of choice is FrontPage. There will always be graphic artists, who don’t know, how to draw a human figure.
    They are not important, regardless of how successful or productive they are. They do not set the bar. These enthusiasts do.
    People will go to their sites to challenge, entertain, or puzzle themselves; often – to steal ideas, scripts, and hacks.
    And this is how the web evolves; and not only web – everything works in a very similar way in our world.
    Where would the whole huge pop music world, if they would not be able to feed on the strange, exotic and disturbingly weird legacy of avant-garde jazz, alternative rock, folk, and neoclassical experiments of the beginning of the last century? Chances are, nowhere.
    Those are the rules of evolution…

  53. Scotacus: I think you’ve got it backwards. The inclusion of hacks is actually a concession to “lunch-bucket nuts & bolts guys” like you. Or us. Or anyone who earns a living off the web. Without them, we would be at the mercy of the buggy layout rendering engines of browsers, and CSS based designs would be a pipe dream or would necessitate the revival of the “best viewed with” button (and I’m sure nobody wants that).

    Hacks are part of the current reality of CSS. We have to live with them, in much the same way we had to put up with the tag when it was all we had. In a few years, when the browser makers have finally standardized enough, we may part with them (happily), but now they are tools geared towards pragmatic development.

  54. Sergio:

    I would agree that hacks make certain fx accessible (if one has the time, unusually patient client, resources [os, browsers, monitors etc]). Yet, there is much one is able to accomplish using css or hybrid standards w/o hacks.

    With the enthusiasts I have no complaint. You are right: those that contribute to this & other sites are stretching the barrier.

    However, standards were designed to escape the spaghetti-coding, home-brew remedies of site development. I agree it is nice to look “under the hood” & find separation of content & layout. Yet, in “n” years time, the main browsers will have largely caught up. All those hacks that pollute the code will cause issues. In order to reconstruct a site I will have to know what each obscure hack does. How is this any better than picking through embedded tables?

    A suggestion for this site, if it wishes to retain its usefulness in the worthy crusade for standards, would be to acknowledge that css & standards are not one and the same. This seems to be the creeping logic – that if one is using css (even with hacks) then one is using standards. Not true. This site should denote when an article complies with strict standards & when it is experimental. The only way around this is if w3 recognizes or standardizes the hacks. Then using hacks == using standards.


    The analogy of evolving music is not applicable. The music you mention does not have centralized standards, it has styles, perhaps methods. Centralized standards are meant to provide homogeneity in professional applications. Any “evolving” from these standards becomes “style” & is, by definition, arbitrary & separate from the centralized standard (ie w3). Perhaps, these styles will eventually become standards (centrally recognized rather than popularly accepted).


    There is nothing wrong with experimentation or styles as long as they are recognized as such & are not confused with standards. It perhaps is a matter of degrees the length one is willing to stray from standardization. Accordingly, one would then mostly use standardized coding, whether its with hacks or tables or whathaveyou.

  55. “All those hacks that pollute the code will cause issues”

    That’s why the anatomy of most hacks is the following:

    1. Define correct, standards based behavior for compliant browsers.
    2. Insert hacky code that caters to non-comp browsers (a comment here indicating this is a hack may be appreciated).

    This is forward-thinking. When X browser starts complying, you can just remove the hack and leave the rest. It should work. As an example, I have an overflow: hidden property commented in my site’s stylesheet due to a specific Gecko rendering bug. The comment states the bug number and that the line should be uncommented when it is fixed.

    Yes, it’s ugly, but it’s the best we have. I sometimes find it more problematic to try to develop entirely without hacks, because there are too many things that don’t work the same across browsers.

  56. Dont mean to beat this thing to death but…

    Re resorting to ‘the revival of the “best viewed with” button…’ I dont see why this would be necessary by keeping to standardized code. A simple browser-sniffer would decide which style sheet to use.

    Seriously, I cant think of a professional that would spend hour after hour trying to hack or convolute the coding so it works in all browsers when he could simply use browser detection. However, I know that enthusiasts would spend same hours because for them its a hunt, a challenge, complete with bragging rights.

    Notwithstanding the many excellent articles I have noticed that some articles explaining a new technique or hack are met with puzzlement: “Ok. Neat. But… why…?” Often the technique is more time consuming (& time is nothing to an enthusiast) & completely “spaghetti-fies” css coding. But please dont say it is done “for the sake of standards”. It is rather for the sake of using CSS.

  57. I agree with your point re removing hacks {http://www.alistapart.com/discuss/onionskin/7/#c8293}. Other than bloated and convoluted coding there should not be any other issues.

    But my other points remain valid. If you experience such hardship re cross-browser issues (as we all do!) then why not use browser detection? Then you could retain standardization without risk of it being buggy.

  58. “then why not use browser detection?”

    Most browser sniffers rely on javascript to work. Most javascript code has to implement two or three different ways to reference elements in order to cater to different implementations of the Document Object Model.

    The most effective browser sniffing techniques do not rely on asking a browser who it is, but rather, they detect unsupported properties. This is not standard compliant behavior. In most instances, you’re taking advantage of a bug or a faulty implementation. In a way, you’re not getting rid of hacks. You’re just moving them to another technology. Plus, you’re adding the extra requirement of having javascript enabled to see your page correctly.

    I’m not against these methods at all (in one of my articles I talked about Conditional Comments, which I rather like), but don’t think that this is any more correct than using CSS hacks. And, if you’re resorting to use only one version of DOM referencing in your javascript, you must be supporting a really low number of browsers.

  59. Sure, standards are designed to escape the “spaghetti-coding, home-brew remedies of site development.” But you know what? Once you banish all clever coding and hacks to the wayside, then you lose creativity and ingenuity. If the purists had their way from the beginning, you wouldn’t be looking at images on the internet right now because that’s just fluff.

    No matter how great the standards become, there are going to be limits to what they “allow” you to do. I for one would rather see designers and developers push those limits and create beautiful and innovative sites that might not be 100% standards compliant, than compliant sites that are a boring rehash of the same available tools.

    Nobody is forcing you guys to use this method if you don’t want to. And it’s a really clever way to solve the problem of dynamic dropshadows, regardless of how much code it requires or if it’s semantic or not. If your blind hatred of anything that the W3C doesn’t approve of won’t let you see that, then that’s your loss, but stop presenting the same tired arguments against people trying new things. People trying new things is what got all of this here in the first place.

  60. Scotacus — You’ve made a good point, and I agree: using CSS for the sake of using CSS has very little to do with standard-based design. I think, ALA understands it very well, otherwise they would never preface this article with the editorial note it has. The “classification” of a future material, however, might get somewhat tricky, unless they will come up with some sort of compliance-rating scale for a code… So far, we just have to live with a regular validation routine.

    In defense of my music analogy: music IS, perhaps, the most standardized artistic realm here is (starting from A = 440Hz, doesn’t get any stricter, than that, does it? I am not even going to touch the scales and chords…); let me rephrase it:
    If not for the plantation slaves, who introduced us to [initiative, or proprietary standards – quirks mode, if you wish] minor and major blues scales, which were later adopted and developed by jazz musicians [initial acceptance of a standard], we would never have neither rock-n-roll [style or method], nor Stravinsky’s “Ebony Concerto” [wider acceptance of a standard, neo-classic application]; without the fusion of classical music [standards – strict], jazz [standards – transitional, and quirks, a lot of them], and world folk [quirks mode, again, very ethnicity-specific], classic rock would never emerge as a style or method, and there would never be anything remotely resembling disco, techno, country, or rap in the form we know them now. No cotton – No Armstrong – No Primo – No Elvis – No Queen – No Outkast or Spears… (Hm. I wonder, if that would be a good thing?)
    Pop music [WWW] employs whatever works [styles, methods, and whatever standards, hacks and quirks there are], and easy to implement [$$$].
    The point is: somebody has to start somewhere, in order to make things move.

    Will — “People trying new things is what got all of this here in the first place”. Exactly my thoughts. However: writing standard-complaint code has nothing to do with one’s creativity, it’s just a way of constructing your layout, and there are many, and many of them are legit.

    “Palying a piano is not that hard – all you have to do is hit the right key at the right time…” — Who said that?

  61. Will: Did you actually read what I posted? Do me a favour & count the number of times I congratulated or thanked or praised this site and its contributers.


    IG: You make a valid point regarding the note at the beginning of this article & I think that is the kind of acknowledgement that is essential. Re a rating for code in relation to compliance, that’s easy – take the code & run it through w3 validator.

    Unfortunately, (& I believe it is relevant), only one has recognized that css is separate from standards, that using css without standards is no different than using tables for layout. However, one gets the sense that if one suggested a site called http://getjiggywithtablesforlayout.com he would be branded a philistine. Double standard – but not web standard.

    Actually, I think I am but pointing out the obvious. That most others refuse to see it confirms my point.

    CSS != web standards

  62. I’m sorry, I didn’t even see your first post – only the second one I quoted from.

    Yes you have praised ALA, but in the same breath you also imply that it’s not really a good resource except for hacks – which is a pretty underhanded compliment.

    Web standards are NOT the life and death situation that many of you “nuts & bolts” guys treat them as. Yes it’s great for us all to work towards our development and code being uniform and universal, but it’s not ESSENTIAL. The web won’t fail if someone uses a few extraneous divs to create an effect that the standards wouldn’t otherwise allow. The web is not SOLELY about information – not every site can break down to a core body of text. It’s also about experience and when you deny the validity of innovation and experimentation because they don’t conform to a standard, then you neglect the experience.

    The code is a means to an end. Anyone with a knowledge of semantic markup and standards compliant code gets a feeling of satisfaction from doing it the “right” way. But in the end most projects aren’t judged on how complaint your code is and if it validates as XHTML Strict. Most projects are judged, by the client, on whether or not they market to the audience and accomplish any number of corporate goals. A CEO doesn’t know that the code for his site validates or not. But he does know if people are using the site and attracted to it. And sometimes to stand out and offer new and exciting things to people, you have to use a few hacks. That’s not the end of the world and that’s not a reason to castigate people’s work.

    If you can’t accept the standards as a favored guideline rather than a strict rule, then you’re lost touch with the reality of web development.

  63. Will, its not simply a case of “don’t do that aas its not standards-compliant”, though thats certainly part of it and something people have been fighting hard for now. Several people have introduced ways of achieving this effect through better methods (ie using javascript to insert the additional markup or server-side technologies) which have many advantages.

    This is also about not having to insert more junk markup into your code to achieve something as simple as a drop shadow.

    Likewise, I do not dismiss this article entirely because the idea itself is good, and the technique most certainly works. It is merely the implementation I feel that can be improved on, and only 5 pages into the comments, already 2 people have come up with good javascript solutions.

    I simply say to you, if you want to simply accept an article rather than constructively criticising and saying “what can be done better here?”, use the additional markup and take IMO a few steps backwards, feel free. Nobody is forcing you to do otherwise.

    “blind hatred” – come on now, theres no need to start putting words into other people’s mouths.

  64. Will, I agree with everything you posted 2 stops back.

    However, the note at the start of this tutorial is important. And I’ll try to explain.

    I tuned into this site via Zeldman’s book on CSS and web standards (as mentioned earlier Ive been out of the loop for a while). He goes to some length hilighting all the great rewards of separating style from content. Im sure we’ve all read it. This site is endorsed by his “evangelism” & in turn evangelizes CSS/web standards, first by redesign & through the philosophy behind the content & those it links with (Meyers et al).

    From there, one does (or am I the only one??) get the sense that CSS is considered superior compared to non-CSS (as I think Luke was pointing out) because of CSS’ affiliation with web standards.

    Thus, the logic is extended that any hacks implemented to bring about desired effects is within the spirit of web standards & thus still preferable (ie “purer”, better) to, for example, using javascript for the same effect (again a nod to Luke & others) or godforbid, tables.

    What is being done with CSS to create hacks is essentially the same thing as using tables or javascript to make things work. All these measures are done without referal to standards.

    But I notice that people are developing really clever ways (Im only referring here to ideas that roam outside of web standard comliant use: hacks & other tricks that convolute CSS code) of doing things that could be done (or is already done) simpler in other ways.

    One must ask the question “Why”? If a way already exists to do something, that is simpler & a more effecient use of time, why try to fix something that aint broke?

    There are only two answers within my reach:

    1. Because they are CSS enthusiasts who love the challenge. (Something I, personally, IMHO, have no problem with). or
    2. Because there is a sense that “if I break the standards using CSS its still somehow within the standards or at least better than breaking the standards using non-CSS”.

    I have nothing against innovation, using what suits you & leaving the rest. & its ok to break whatever rules necessary to get a job done; this is a fact of design life, for now. But I dont(or perhaps I do now) understand what seems to be a type of CSS fetishism – that it’s the cool new style & also official & valid due to CSS’ popular affiliation with web standards.

  65. Scotacus: Read my previous comment ( http://alistapart.com/discuss/onionskin/7/#c8296 ). Javascript is as full of hacks as CSS, if not more. There aren’t two implementations of the DOM out there that behave the same. Event catching and bubbling is a nightmare to work with if you want to do it cross browser. You keep touting javascript as the end-all be-all for this kind of thing, and I still see it as an incomplete solution.

    Not to mention that you add another requirement to users in order to see your site correctly (having javascript enabled) and thus needlessly increase site complexity.

  66. sergio > By using javascript to add nothing more than a drop shadows, you aren’t adding an additional requirement to your website. Is it the end of the world if the user with javascript disabled doesn’t see your funky drop shadows? They still have access to your site and no harm is done.

    Admittedly javascript code requires object and method detection and a bit of patience to get working correctly cross-browser – however the other great thing about javascript is that the authors often release their code for other people to use, meaning you don’t have to do much hard work either.

    Javascript gets a raw deal. Linking to a simple script in your page does not needlessly increase site complexity in the same way that adding lots of extra divs does IMO.

  67. luke > By using *CSS* to add nothing more than a drop shadows, you aren’t adding an additional requirement to your website. Is it the end of the world if the user with *unsupported browsers* doesn’t see your funky drop shadows? They still have access to your site and no harm is done.

    Admittedly *CSS code* requires ** a bit of patience to get working correctly cross-browser – however the other great thing about *CSS* is that the authors often release their code for other people to use, meaning you don’t have to do much hard work either.

    *CSS* gets a raw deal. Linking to a simple *stylesheet* in your page does not needlessly increase site complexity in the same way that *adding extra scripting does*.


    See what I did there? I hope that’s clear.

    As for the extra

    ‘s: You’re dissing this particular technique because it uses three

    ‘s. I have already demonstrated techniques to achieve this effect that use two and one

    ‘s. If you don’t need a frame around the image those can be implemented using one and zero

    ‘s, respectively. I just don’t see your point, or reluctance to use CSS for these effects. I’m afraid that you’ll have to do better than “it’s too complex”.
  68. I’ve enjoyed reading this article, reading the discussions, and getting all worked up over using it.

    Then I tried to implement it, and have fallen on my face a bit. I’m using Zac’s fine JS solution which is behaving the same as the 3 DIV hardcode solution. That is, I still have the same problems, so I doubt Zac’s JS is the culprit. I can’t escape the float:left problem. I’ve wrapped it in other divs, which it floats out of. I just want to align a shaded image to the center of a page. (insert eyes tearing up…) *sniff* and I don’t want to use tables to do it…

    any help for the brain dead?

  69. I think Zac’s javaScript + onion skinned drop shadows is totally rad, and I plan to use it soon. One thought I had was to have the js load css for the shadows. That way if js is off the extra css won’t be loaded.

    I’m always amazed at how quickly ideas get developed here. Thank you.

  70. EyePulp –

    Sorry to have confounded you with the left-leaning technique. Unfortunately, there is no explicit property for collapsing a div around its contents, so float:left must be used until something better comes along. There is a solution to your problem, however…

    I’ve put together a modification that you can use to center an object with the shadow applied:


    This mod is only the first thing that jumped to mind when I considered your problem. I would encourage you (and others) to investigate it further. There’s ALWAYS more than one way to skin a cat.

  71. Scotacus, okay now I TOTALLY agree with you. A hack is a hack is a hack. Be it with tables or a bunch of divs layered to achieve an effect, it’s still “technically” a hack either way when viewed in light of the standards. I also agree that the mindset of many is probably that CSS hacks are okay. I think this is a byproduct of the set with whom it’s fashionable to display all your xhtml and css validation links. Sure your page might validate perfectly, but that still doesn’t mean that you’re actually developing to the true intent of the standard.

    I missunderstood you earlier and thought you were arguing against deviation from the standards, but now I see that’s not really your point and I apologize for putting words in your mouth.

    My only point in this whole argument was that standards are great but sometimes cleverness is greater.

    I guess at least if someone is hacking with CSS they’re moving in the right direction from a skillset standpoint, even if it’s not the right direction from a markup standpoint… 😉

    Anyways, kudos to everyone in this discussion. Not only some great ideas and solutions put forward in the onion-skinning concept, but some great discussion about it all too.

  72. Will:

    Im not evangelizing strict standards; dont get me wrong, I use hacks. NOt for dropshadows (though I may get around to it if I find the time). Right now, to get up to speed, Im looking for the best, broadest & quickest methods. My clients dont care if I use css or graphics to get an effect, but I cant justify tweaking & tweaking & tweaking(etc) just so I can say “See the cool effect!” Id rather spend that time doing something else (like working on another site, or maybe, someday, eventually mine).

    Ive already taken somethings from this site & emplemented them & I agree – thats what its all about, to be able to pick pointers here & there and build a tool set. This particular technique is valid on its own (I havent investigated other ways of perhaps doing it). It might be great to have in my tool set but right now I have other, more pressing things that need priority.


  73. I tried printing this document out for later reading, but it refused to do so. I noticed that I couldn’t select the images … I don’t have time to dive into the CSS, but perhaps something’s off with the print stylesheets.

  74. One of my new sites, YoungAmericanVoters.com (which is not yet finished, still in design stages) tries to encorporate this “dropshadow” by using only a slightly bigger border on the bottom. This is sort of a cheat.

    If you think this was pulled off, or have any other recommendations for the site, please don’t hesitate to email me at admin AT sandwiregames DOT com

    Thanks in advance.

  75. I don’t like the div’s abuse but, why not using a fourth layer to put the bottom right corner? This way you can use smaller graphics and you can do your shadows bigger sizes.

    Sorry for my English.

  76. But it’s a bit facile. The javascript/css solution lets you add the effect without out cluttering you html and can be made to fail more gracefully than the pure css.

  77. Am I the only one having to cope with
    backgrounds that are not made of a solid color but a gradient ?

    Sure you might say, there’s ALA’s “Creating
    Custom Corners & Borders Part II”, *BUT*
    all techniques I have so far seen only
    work reliably on a solid background.
    Our beloved Internet Explorer can’t
    handle alpha transparency for images loaded
    to the background ! Of course there’s
    Microsofts AlphaImageLoader, but that – as
    I just mentioned – does not work on

    So, how about a technique for dropshadows
    that work against a gradient background ?

    Hints, Tips, RTFM’s anyone ?

  78. This would be a perfect case for the technique that Luke Redpath. outlines in CSS Limitations Part 2. Allowing for elements to automatically contain other elements would prevent all of those extra DIVs in your markup. Sorry if this point has already been brought up, but I haven’t yet read this entire discussion.

  79. This article is very clear and the diagrams are very helpful. I think this technique is a step in the right direction.

    I tried it on a coloured background and the wrap1 div seemed to have a white background, which I am racking my brains as to how get rid of. I’m new to this game so it’s probably something I have missed (css makes me feel that way quite a lot!).

    If only css did everything it says it can. Mind you browsers probably have something to do with it. Patience is a damn virtue.

    Thanks for the inspiration.

  80. I found this method very good and pleasing.

    What’s this arguing about extra markup for design. Of course we have to use extra markup.

    When we get a design from a designer, the designer has to design for the best interest of the customer who visits the site, or in the best interest of a good design. Don’t make a design css in the best interest for css..

    A few years back we incorporated designs in our cms, and we made them with tables.
    The designs were all photoshop psd files, and there was no clue from the designer what html could and couln’t do. And not a single design had to be done over because it wasn’t possible in html.

    Nowadays we shift more towards clean xhtml and css. But we can’t say to customers now : ‘ that designs with dropshadows have to be adjusted because the html cannot do that.

    It would be stupid that what we could do in the past, can’t be done in the future.

    also, it’s a bit of a myth that the whole sit e could be redesigned with just the css. Yes, I have seen zengarden, but they also have extra divs in the html for logos and such.
    And the nesting of divs sometimes still has to be adjusted to get the results in a new design.

    The only way to do css layout changes is to stick to the stramien of the hierarchy in the html.

  81. Well, three extra

    tags or so to create visually pleasing sites? I’m for it.

    If the result is good enough, and the visual interface is more important than file sizes. It’s still better than a table layout. A table layout with drop shadows like this would require even more code.

    It’s been said before. Creating drop shadows with tables was also a pretty advanced technique, only more clumsy than with xhtml + css.

  82. I liked the idea but neither the DIV version as the JS is working in my site if you want to align your image to the right…
    Well at least I didn’t get it to work but then I might be a total NOOB…

  83. This technique does destroy the sanctity of using web standards. It’s an advanced aesthetic design feature that exploits the flexibility of the markup. Doesn’t make it wrong. But it may not make it right in your individual eyes either.

    We can all keep making boxes with 3 pixel borders though. Techniques need to be exploited. They need to be pushed and some rules need to be broken. Then we can all sit back and see what we’ve done and learn from that.

    It the concept that has brought us all this far and it hasn’t failed us yet.

  84. I tried plugging this into my website on a single image and it basically failed .

    it moved the image to a higher layer and showed no dropshadow effect whatsoever.

  85. Can you make the shadow go all the way round an image. I thought of putting in 2 more div’s with the other 2 corners in then and giving the shadow a 4px fade on all sides, but the shadow doesn’t resize so if it’s possition is set to bottom right then the top and left borders don’t work.

    Any one got any great ideas to solve this or can’t it be done?

    Thanks Great scrip

  86. I’ve only read a handful of the comments, but it was enough to have me rather surprised at the amount of opposition to the very small amount* of additional markup.

    * at deviantart.com, we’ve been using 8 wrapper divs around every section area (average 10 per page), to have graphical borders surrounding these boxes, even though our primary ‘skin’ hardly uses them any more. The whole thing’s in need of a good dusting, but it’s cross-browser ambrosia, still.

    It seems to me that a lot of people are putting themselves inside a theoretical web that exists only in the specs of the W3; the semantic web, a properly refined XHTML, and a level of CSS that would afford the control simulated in this article (via ::outside and border-images(?)) are the systems needed to put together a shadow effect like this, devoid of mingling of content and presentation; and these systems do not exist: they are still on paper, they are still just ideas, and they are waiting for the fine thinkers to approve them, for the fine doers to implement them for the public, and then waiting years for everybody else to catch up with their software upgrades and finall avail of it all.

    Now I love the W3 and its specs; the sheer effort put in has produced unimaginable quality– but while the above conditions are unmet, while the core infrastructure of the standards is still being put together, and while 90% of the web’s population use a browser that does a fine job of ignoring these standards anyway, then by all means care should be taken to adhere to the standards- but for goodness’ sake, don’t drop an easy to implement div-based system because it makes the code look untidy by the standards of a few years in the future.

    As it stands, in practise, the minimal content-style separation we currently have available to us already does so quite robustly, all the way from Lynx to Opera; if it’s WCAG friendly, and it is, then it, to me, is a fine 2004-2006 solution.

  87. I recently found a tutorial at redmelon.net using this idea for creating standard corners for any box on a page.


    If you put this together with ZACs’ javascript idea to reduce coding.
    Then use a separate style sheet for various types of corners.
    Only one class or id will be left in the code if you decide to revamp a website.

    This could be reused for an entire website

  88. This technique only uses 3 divs including the one holding the content.
    That is only 2 extra divs.

  89. well, it works perfectly!

    but how to center these containers?

    does not work. (due to float:left???).

    who can help me?

  90. Has anyone tried alpha-blended drop shadows using PNGs? I’d really like to find someone who has done this, including that filter workaround for IE.

    For the likes of Mozilla/Opera, etc, this drop shadow stuff with semi-transparent PNGs is great =)

    Only quirk: putting the divs around an existing div seems to break a lot of the layout — seemingly the float: left is the culprit =(

  91. Thanks for this helpful link, Brian. It works fine, but now there is another problem:

    Having seen your Article “shadow visible on all sides”, I tried to center these four containers – without any success 🙁

    #wrap0, #wrap1, #wrap2, #wrap3 {
    /* */display:block;/**/
    #wrap0 {
    float:right; right:50%;
    background:url(shadow.gif) right bottom no-repeat;
    #wrap1 {
    background:url(shadow180.gif) no-repeat;
    #wrap2 {
    background:url(corner_bl.gif) -16px 100% no-repeat;
    #wrap3 {
    padding:4px 6px 6px 4px;
    background:url(corner_tr.gif) 100% -16px no-repeat;
    #center {
    width:1%; margin-left:50%; float: right;

    (this centers the image, but it shows also an awful border on the right side.)


  92. Smoother,
    Try this…


    Bear in mind, with both a 360 degree shadow and centering at work, you’ll begin to see issues that require additional CSS to work around.

    For instance, when centering http://www.ploughdeep.com/onionskin/centered.html, if you choose to put a shadow on a block of content instead of an image, you’ll need to declare a width for the block or else it will collapse – or stick something inside that forces it to expand.

    Additionally, like I said before http://www.ploughdeep.com/onionskin/360.html, offset values in the CSS become very sensitive to the dimensions and whitespace built into your shadow components. You’ll need patience, good problem solving skills and Photoshop to get this one right.

    These are quick fixes. Improvement is likely – please share what you find.

  93. Dear Brian,

    your version takes the same effects like mine. That is why I decided to use tables.

    This (non-css) works fine.

    Nevertheless I want to thank you for supporting me.

    greets from germany,

  94. I’ve implemented Zac’s js with the onion skinning and everything works great – except links from a drop shadow image do not work in ie (5.x and 6). In Firefox, Mozilla and Netscape the links appear. Has anyone run into this issue?

  95. The javascript/css solution lets you add the effect without out cluttering you html and can be made to fail more gracefully than the pure css.

  96. Brian,
    Thanks for the tutorial on onion skinned dropped shadows. These things
    work great. I wanted to give something back to this subject and add extra
    functionality to these. I created a simple php function that will make
    using these drop shadows much easier. It even adds in one extra feature.
    This function automatically scales any image that is larger than the main
    shadow to the size of your main shadow.

    Here is the code:

    < ?php function dropShadow($image, $right, $down){ /* args = image, pixel padding positions Shadow size is width = 475 height = 470; Please note that this function scales images over height 470 and or width 475. If I don't want to do this, change the shadow image size. Also note: that if you don't have all error reports turned off on the php server, and you use the function without all the arguments, error will be displayed. However, if you have your error reporting turned off, you don't need to use all of the arguments. */ if($image){ $size_info = getimagesize($image); // returns array {width, height, image-type, string} if($size_info[0] > 475) // comparing width
    $altered = true;
    if($size_info[1] > 470) // comparing height
    $altered = true;
    if($size_info[0] > $size_info[1]){ // image is wider than taller
    $ratio = 475/$size_info[0];
    $width = 475;
    $height = $size_info[1]*$ratio;
    elseif($size_info[1] > $size_info[0]){ // image is taller than wider
    $ratio = 470/$size_info[1];
    $height = 470;
    $width = $size_info[0]*$ratio;
    $height = 470;
    $width = 475;
    $width = intval($width);
    $height = intval($height);
    $image = “swirl.jpg”; // default image
    if(!$right || !$down){
    $right = 10;
    $down = 13;
    echo “n

    echo ‘
    The object casting a shadow


    < ?php dropShadow("portfolio/Guitar.jpg", 13, 16); ?>

  97. If you copy and paste the above code, please make sure to take into account that I didn’t take into consideration how this narrow column wraps my code. Look for wrapped single commented lines (//), and look for anything else that doesn’t look right.

    Sorry for the confusion.

  98. This should fix the wrapping issues for the code if you want to cut and paste.

    < ?php function dropShadow($image, $right, $down){ /* args = image, pixel padding positions Shadow size is width = 475 height = 470; Please note that this function scales images over height 470 and or width 475. If I don't want to do this, change the shadow image size. Also note: that if you don't have all error reports turned off on the php server, and you use the function without all the arguments, error will be displayed. However, if you have your error reporting turned off, you don't need to use all of the arguments. */ if($image){ $size_info = getimagesize($image); /* returns array {width, height, image-type, string} */ if($size_info[0] > 475)/*comparing width*/ $altered = true;
    if($size_info[1] > 470) /*comparing height*/
    $altered = true;
    if($size_info[0] > $size_info[1]){ /* image is wider than taller */
    $ratio = 475/$size_info[0];
    $width = 475;
    $height = $size_info[1]*$ratio;
    elseif($size_info[1] > $size_info[0]){ /* image is taller than wider */
    $ratio = 470/$size_info[1];
    $height = 470;
    $width = $size_info[0]*$ratio;
    $height = 470;
    $width = 475;
    $width = intval($width);
    $height = intval($height);
    $image = “swirl.jpg”; /* default image */
    if(!$right || !$down){
    $right = 10;
    $down = 13;
    echo “n

    /* take out the » 2 lines down */
    echo ‘
    The object casting a shadow


    < ?php dropShadow("portfolio/Guitar.jpg", 13, 16); ?>

  99. Hey All,

    I’m not sure if anyone posted a similar solution (I didn’t read all 12 pages of discussion!) but here’s one way to programatically add in the image DIVs.

    Put this in the head of your html:

    and then just add class=dropshadow to any IMG tag you want to have a dropshadow.


    PS -- this code uses the lib_c.js library that was mentioned in the article "Accessible Pop-up Links" and which can be found at

  100. Yeah, PHP and the GDlib are go for drop-shadowing, so long as you write the image to a directory rather that have the server do the calc over and over. On-the-fly image manipulation is server-intensive. Unless you need the non-shadowed version intact yet don’t have the space for duplication.

    I did a preliminary looksee, and couldn’t get this div-div-div onion skin to shadow a table, rather than an image. Or how about another div serving the same function?

  101. First of all: nice article, William. It’s not the uber-trick i’ve expected, but as someone mentioned before, really great for photogalls and so on.

    I like and prefer Zac’s idea using JavaScript to add the extra-stuff – so the whole thing looks really clean, except the IE-Mac hack; is leaving the Maccies here without shadows an option maybe? Or should we all wait for CSS3 to become rendered in future version, maybe Opera 8 next time, or IE 8 in plenty of years? 😉

    One litte thing OT:
    Faruk Ates’ Hawk-Eyes found the background-image bug, but that could happen to everyone. So much background, -sound, -image, -color… oh, background-color? “It is all white – it is all right”.
    Sorry to complain, maybe its just my envy, but it makes me sad after reading a good article/source and statements like “…His design of Calibre.com is the company’s proud foray into standards-based design.” and then seeing there is no default bgcolor.

    Then i thought: well, let it be, it will be added soon for sure, but one minute later i discovered the same at http://www.ploughdeep.com/onionskin/ – or is this a huge shadow and not my default-lightgray background-color? 😉

    Hope you’ll fix this asap so we can del-edit my dont-post-so-late entry.

  102. Thank You:
    *Solve this problem by using tables | by smoother*

    I used the above fix to get things to display properly in Netscape 7.

    FOr some reason, the drop shadow width was expanding and breaking the layout. Placing the container in a table fixed that problem. Thanks.

  103. Hi,

    First off I’ve seen the article by Brian Williams about horizontal centering and it works a charm. The problem is that I want to center this image and it’s drop shadow not only horizontally but vertically as well. Now I’ve searched for this on the web and there is loads of info which I’ve tried but most work only with an image by itself….. as soon as I add the shadow everything goes pear-shaped. Before I clutter then forum with my code I was wondering if anybody had an elegant solution/hack? below is the layout I’m going for:

    |div. | div.main |
    |left | ———– |
    | | | image | |
    | | | with | |
    | | | shadow | |
    | | ———– |
    | | |

    i realise there is a CSS weakness with vertical centering but there must be some way of doing this as it’s such a common thing to want to do. One other thing is that the image can be of either any dimension less then the max and can be either portiat or landscape.

    Maybe I shouldn’t be using this shadow trick but it seems so much cleaner then the table version.

    Many thanks

  104. Ok, so apparently I can’t even get posted format looking the way it should (sigh)…. let me try again (assume fullstops are whitespace!):

    |div..| div.main …..|

    I was reading somewhere that you can’t actually do this with CSS so if that’s the case then that’s alright I’ll do the shadow and centering with tables. I was trying to avoid that.


Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

Nothing Fails Like Success

Our own @zeldman paints the complicated catch-22 that our free, democratized web has with our money-making capitalist roots. As creators, how do we untangle this web? #LetsFixThis