CSS Drop Shadows II: Fuzzy Shadows

We like shadows. We enjoy making them drop and we love CSS and standards, so we wrote CSS Drop Shadows. The little voice in our head approved of it. We thought that was the end of it.

Article Continues Below

We thought wrong.

The internet being the kind of medium it is, minutes after the publication of the article, we started receiving comments, queries and suggestions for improvements. Most notable among the latter was Phil Baines’ method for keeping the markup simple when dealing with paragraph drop shadows. We are indebted to him.

The most complained-about shortcoming of the technique turned out to be the sharp top and left edges of the shadow, which, although generally acceptable, are unlike what an image editing program would produce (a fuzzy shadow). Given that the shadow image is effectively clipped at those points, we felt this was an unavoidable inconvenience, chiefly due to Internet Explorer’s inability to display PNG’s transparency natively.

A cat's nose
A cat's nose



blowup of shadow detail


Then Jan pointed out a technique for making Internet Explorer render PNG’s alpha channel correctly. It works by activating Explorer’s AlphaImageLoader filter (previously discussed in this ALA article), but does so in an inobtrusive way which requires no extra javascript code. We think it’s a godsend. Combining this technique, some image trickery and our “fake shadow offset” method, we’ll be able to make properly fuzzy shadows that work across browsers.

In this article we’ll learn how to:

  • Hide a stylesheet from non-IE browsers so it doesn’t affect document validation.
  • Coerce IE5.5/IE6 into displaying PNG transparency correctly.
  • Use the above to create fuzzy shadow edges for our Drop Shadow effect.

First, we’ll fabricate our fuzzy shadow edge. To do this, we must create an inverse shadow in our image editing program. Usually we’d use a black shadow over a background color. For this effect, we’ll need a colored shadow. It must be the same color as the background over which we’ll apply the effect.

Start with an image like the “fake shadow offset” we described in the previous article. This one should be thinner than before (about 3px thickness for a 6px shadow has worked out well for us). Our examples will use white as background color. When reproducing this technique, adjust for yours.

We’ll apply a “Drop Shadow” effect to this image, taking care to specify white for the shadow color. A strong shadow is desirable — the stronger it is, the faster your shadow will seem to fade. We should now have something that looks like this:

Fake Shadow offset image


Save this image as a PNG with full transparency. We’ll use this file for IE5.5, IE6 and standards compliant browsers. Make a regular version sans shadow with thicker offset (as seen in the previous article) and save that as a GIF file. We’ll feed this one to IE 5 (which does not support the AlphaImageLoader filter). Here are sample files for your perusal: PNG/GIF (Check them on an image editing program, since they will look like white on white in your browser).

Since we now have a solid color at the edge of our offset, we’ve effectively given up on the possibility of having a transparent shadow, so we’ll use a simple GIF for it. Make sure you apply the effect over the background color you’ll use. Here’s our example shadow: GIF.

The markup for this effect will be two <div>’s around our image/block element.

<div class="alpha-shadow">
  <div>
    <img src="img/test.jpg" alt="just a test" />
  </div>
</div>

The basic technique is still the same: We’ll set up the fake offset (with its inverse shadow) as background of the innermost <div>, and the shadow as background of the outermost one. When overlapped, the transparency of the PNG will seem to gradually dissolve the shadow image until it becomes the solid background color. The tricky part is making this work in Explorer.

Illustrated process


Our CSS is pretty much what we had seen in the previous article:

.alpha-shadow {
  float: left;
  background: url(img/shadow1.gif) »
  no-repeat bottom right;
  margin: 10px 0 0 10px !important;
  margin: 10px 0 0 5px;
}

.alpha-shadow div {
  background: url(img/shadow2.png) »
  no-repeat left top !important;
  background: url(img/shadow2.gif) »
  no-repeat left top;
  padding: 0px 5px 5px 0px;
}

.alpha-shadow img {
  background-color: #fff;
  border: 1px solid #a9a9a9;

  padding: 4px;
}

If you look closely you’ll notice we’re still including the non-fuzzy GIF offset (shadow2.gif) as background of the inner <div>. This is for the benefit of Internet Explorer 5.0, which doesn’t support the AlphaImageLoader filter. As it stands, this code will apply to all versions of Explorer. To make adjustments for IE 5.5/6, we’ll create an extra CSS file.

ie.css#section2

To activate the AlphaImageLoader filter in a simple and reliable way, we’ll first include it in its own CSS file and name it ie.css. We know this is shameful and will probably make the Standards Squad put a price on our head, but we’ll hide this file from other browsers later, so it’s ok. Kind of.

Our ie.css stylesheet will look like this:

.alpha-shadow div {
  filter:progid:DXImageTransform.Microsoft»
.AlphaImageLoader(src='img/shadow2.png', »
  sizingMethod='crop');
  background: none;
}

The AlphaImageLoader filter supports two sizing methods: crop and scale. We’ll use crop for our offset (scale fits the full image into the block, and is not what we’re looking for). Since the filter is somewhat limited and does not support CSS-like image positioning, we’re stuck with shadows that drop down and to the right (the image on its default position is all the way to the left and top).

We should note that, since the filter places the image in the foreground of the block element rather than as its background, this technique could be set up to show fuzzy shadows in Explorer with only one <div> surrounding the image, and show the hard edge shadow for other browsers. Not being ones to reward bad browser behavior, we’ll stick to the technique with the extra <div>, which gives us a fuzzy shadow in almost every browser under the sun.

The second line, where we set the <div>’s background to none, is there in order to remove the GIF offset we specified in the CSS before. Since we’ll only feed this file to IE5.5 and IE6, IE5 keeps the GIF offset (and thus displays a hard edge shadow). The rest of the browsers ignore that GIF file by the !important method we specified in the previous article.

Conditional Comments#section3

To hide the ie.css stylesheet from all browsers that don’t need it, we’ll use Conditional Comments, a Microsoft provided technique to serve content to specific versions of Internet Explorer. They are included in the html document and look like standard html comments, so browsers other than IE5+ ignore them (and so does the w3c Validator, which is convenient). We’ll insert this in the <head> of our document, after the CSS for the drop shadow:

<!--[if gte ie 5.5000]>
<link
  rel="stylesheet"
  type="text/css"
  href="ie.css"
/>
<![endif]-->

What that does is specify that the enclosed bit of code should be used by versions Greater Than or Equal (the gte part) to Internet Explorer 5.5 (it must be specified as 5.5000 because of Version Vectors), thus feeding IE5.5 and IE6 the special stylesheet.

That completes the technique. This may seem overly complicated just to achieve a fuzzy shadow, but then again, they say that God is in the details. As a plus, the mentioned techniques can be used to achieve all sorts of different effects.

Here, have a cat:

Cat on floor


Acknowledgements#section4

To Jan, who has been playing with this transparency thing for far longer than we have, to Phil Baines, for his suggestions on how to improve the methods exposed in the previous article, and to Ava McBride, for facilitating the use of the Browsercam service for testing of these techniques.

About the Author

Sergio Villarreal

Sergio Villarreal lives in México but spends most of the time in his head. He maintains a weblog and rarely updated webcomic at Overcaffeinated.net and makes a point of learning a new trick every day. Some are even useful.

80 Reader Comments

  1. Well done on the article, and thanks for the name drop. I especially like the conditional comments thing.

    Now, how about another comic strip?

  2. … but I wasn’t satisfied by the answer I read regarding why CSS shadows are preferable over manipulating the images directly.

    If you think of your images as content, then it’s easier to understand the advantages of doing this with CSS. As the look & feel of your site changes, so may your taste in image treatments. By relying on CSS to handle these treatments, you aren’t forced to re-process all of your site’s images.

    On the downside, this particular treatment requires some rather unintuitive nesting of the tag within two levels of

    tags. While the exercise of “massaging” HTML markup to make it stylesheet-friendly has been more or less accepted by designers, we must also accept that it deviates from the general philosophy behind CSS.

  3. Opera 7.0 PC doesn’t render the drop shadows in the last example image the cat) – This is probably triggered by the “float:left” property in the .alpha-shadow div {} declaration.
    Removing the float should fix it.

  4. Then the IE 6 will probably not show the left and top right fuzzy edges anymore when the float:left has been removed. Including the float:left into the special ie.css with the filter style will work.

  5. I have been following this discussion for several days now, and I am still confused about the original idea.
    I will have to repeat myself:
    1. PNG’s alpha transparency is supposed to allow us grater flexibility in positioning images over anything else, while maintaining simplicity of markup.
    2. The situation with IE support can be resolved by many means (I still like the elegance of Aaron’s “Sleight” JavaScript behavior), here is an example:
    http://homepage.mac.com/igstudio/design/css-js-dropshadow/shadow-png.html
    3. If we still have to match background color with GIFs, we could achieve the exact same results with a lot less effort by arranging elements in a table (yes, table – last time I checked it was still a legitimate HTML element – and, yes, it does support CSS formatting, so the separation of content and presentation shouldn’t be a problem):
    http://homepage.mac.com/igstudio/design/css-js-dropshadow/shadow-gif.html
    Look… no JavaScript, no conditional comments, no separate stylesheet… I can go on.
    Please, explain to me, somebody, why we feel the need to scratch our left ear with our right foot? When nestind empty (therefore, not content-bearing, therefore – presentation-specific, so where is a separation?) DIVs became a better way of design than saving the coding efforts and assuring better browser compatibility by using (dreadful) table, which was created to retain rows-columns positioning by design, and perfectly works?
    Forgive me for being fossil, I just want to understand…

  6. iG.STUDiO: This particular approach was intended to minimize markup and maximize control of the effect. Here are some of the motivations behind my decisions:

    – I don’t want to resize an image with the scale control of the AlphaImageLoader filter. Mainly because it does an incredibly shoddy job (yes, I am very anal in design matters). Pixel perfect shadows is where it’s at for me.
    – I wanted good enough results for IE5.
    – I had already done another article on using one

    to achieve a similar effect.
    – I use this technique all the time in my site ( http://overcaffeinated.net ), inside my posts. I don’t want to put a table in there, and two

    ‘s are acceptable to me.
    – I dislike rewriting html documents with javascript. It’s perfectly valid, but it doesn’t rock my boat.

    I don’t think this particular technique amounts to waving a dead chicken over the code, and I find it interesting how many people are complaining about it like it’s a signal of the apocalypse.

    There is a reason this is a *followup* article. This variant may not be for everyone, but people who like their shadows fuzzy and their markup clean may have an interest in it.

  7. I forgot: The technique doesn’t use javascript, and it degrades well. I like to write things that don’t make lynx/w3m/cellphones go berserk.

  8. “Hide a stylesheet from non-IE browsers so it doesn’t affect document validation.”

    That’s great and all, so is this method. But isn’t the whole point of sites like ALA to promote standards? What’s the point of a hack that breaks standards? Even if it is for IE… whose lax PNG support also irritates me!

  9. Sometimes ALA authors get lazy and quickly jump to switching stylesheets ans hiding them from some browsers, which in my view should be a last resort.

  10. Sometimes ALA authors get lazy and quickly jump to switching stylesheets ans hiding them from some browsers, which in my view should be a last resort.

  11. I should stop making comments for the simple sake of not offending anybody. Please… I didn’t mean to, I just wanted an explanation, sorry, if it sounded a bit critical (I like your website… 🙂 🙂 🙂 ). And I didn’t diss your code, Sergio, I merely asked how and why did you arrive to this point.
    I think, that was Igor Stravinsky, who said once something like this (very loose quote): “If I had no limits to my resources, I would probably ended up not writing anything”.
    I think, I see it now. You don’t want tables, so you didn’t use them. I must admit (thanks to a slow day at work), this could really be fun:
    http://homepage.mac.com/igstudio/design/css-js-dropshadow/shadow-div-gif.html
    (for some reason – poor CSS support in this particular part? – IE5.2 for Mac breaks the display, but who cares, it’s dead anyway… It works in IE6 Win, Firefox, and Safari, though)
    Once again, sorry, if my comments sounded apocalyptic…
    It’s all good. Keep up the good work.
    PS. The table-based markup is still shorter. Not cleaner, oh, no, just shorter…

  12. I’m all for CSS advancement but this seems a bit overkill since a regular image with a drop shadow will achieve the same thing – without the fancy tricks. Trying to hack this or that just to satisfy browser quirks is not practical in this case.

    I’ll wait until CSS 3 is more widely adopted.

  13. We use a separate images server on our site and this:

    .img-shadow div {
    filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’http://images.ourdomain.com/shadow2.png’, sizingMethod=’crop’);
    background: none;
    }

    does not seem to work. Is there any way to use teh alpha transparency hack in IE on a “remote” image?

  14. We get a suprisingly large chunk of Netscape 6.0 visitors to our sties. My site and your dropshadow example both fail to show the shadows in Netscape 6.0. I don’t know if this is related but the “Acknowledgements” text is positioned on top of the Free Cat picture.

    This drop shadow method works well in all other browsers and let’s out content writers quickly add some style to a otherwise flat page. Thanks for the help.

    I don’t understand why all the backlash against this technique. It’s give us the flexability of applying drop shadows we need wherever we want without resorting to complex table designs. Our graphic designers don’t have to waste time making two verisons of every image, and our content writers love the new trick they can pull off. It’s valid, doesn’t use javascript, and isn’t to size intensive. Kudos ALA!

  15. Quote:

    “I’m all for CSS advancement but this seems a bit overkill since a regular image with a drop shadow will achieve the same thing – without the fancy tricks. Trying to hack this or that just to satisfy browser quirks is not practical in this case.

    I’ll wait until CSS 3 is more widely adopted.”

    It could be useful for a number of reasons….

    i use it for a content management system where teh client can upload (varying sized)pics to his site, but he hasn’t the software or knowledge to give them drop shadows,

    this allows him to keep the pretty wee drop shadows that he so dearly wanted…

  16. John, I had the same problem with Opera 7.0 but fixed it with “br clear=all” and “clear:both” properties for several HTML elements. In fact I don’t have the Netscape 6 on my machine but my photo site should work on it. You might check it and then have a look at the source.

  17. It’s definitely a cool technique, but I really think it’s a lot of effort (and discussion) over a teeny, tiny bit of return.

    A poster early on said that the hard-edged drop shadows were too ugly to use, but now that they are nicely fuzzy they like them.

    That’s just TOO much attention to detail for me. I think my attention is more productively used elsewhere on site design & maintenance.

    But the article WAS well written, and I appreciate the effort that went into it.

    T.

  18. I can’t get this to work under xhtml strict or 1.1 – I get an ugly lower padding for the inner div… if I do padding: 0px 5px 5px 0px; the Safari and Firefox don’t display properly… if I do padding: 0px 5px 0px 0px; then IE doesn’t display properly… any ideas?

  19. OK, I wrote too soon: the shadows work fine in strict xhtml if you add the following to the img css: vertical-align:bottom; (leaving padding: 0px 5px 5px 0px; for the div). I actually discovered the answer on http://phoenity.com/tests/fuzzy_shadows_anchor.html – thanks to Lim Chee Aun who was the only person I found to implement a version of Sergio’s method in STRICT rather than transitional…!!!

  20. Try removing the » character from your CSS code. That one got me too.

    But I’m having a problem, I’m not getting the rounded corners when I do this through an external CSS file. Works fine when done from the head though…

    Bizarre????

  21. Hi,

    ALA rulez!!
    Question: I float an image and making a border is no prob. The drop shadow won’t float because I already used a float

    Should I use two div’s to overcome this problem?

    t
    Thx for any help.

    CU
    Chazz

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

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career