My original solution to that problem was a Javascript hack that inserts a couple of 1 pixel wide divs at the edge of any element with a shadow class. However, although I have tweaked it several times, it has always been a bit slow. For instance, for the shop front page we're currently rendering more than 60 elements with shadows which takes a couple of seconds with Firefox and Firebug on my old trusty PIII 950 MHz laptop. I'll note that this is actually an order of magnitude faster than the (more general) code I based it on from somewhere else. The really tricky part was decent-speed IE 6 support because that actually required measuring the DOM elements.
However, Firefox 3.5 was released about a month ago, and one of the good news was support for the
box-shadow
CSS3 property. It's a relatively simple property for adding drop shadows. So given that Safari has it, and has had for some time, and most Firefox users will soon have it, it starts getting interesting. For reference, about half of our visitors are Firefox + Safari (+ Chrome which uses the same rendering engine as Safari).If you search for
box-shadow
, some are already using it to add a bit of extra embellishment. However, on YayArt, it's an integrated part of the design. So I had to figure out how to make it work on all browsers.I ended up with a three-way solution. For recent Firefox/Safari/... I use
box-shadow
. For non-box-shadow
supporting browsers, I fallback to the old hack. And for Internet Explorer, I'm using a new hack based on the proprietary filter stuff in IE.Here's a quick sketch. I put this in the general stylesheet:
.shadowed { -moz-box-shadow: 2px 2px 3px #969696; -webkit-box-shadow: 2px 2px 3px #969696; }This makes it work with browsers based on the Gecko and Webkit engines. Some people recommend adding a plain
box-shadow
line, but I need full control over which browsers are responding, and besides it seems to defeat the purpose of the browsers using the -engine-
prefix. Here's a demo:If your browser is recent enough, you can see a shadow here.
Now for the fallback, I need to discover in Javascript whether the browser is using the CSS:
function supportsBoxShadow() { var s = document.body.style; return s.WebkitBoxShadow !== undefined || s.MozBoxShadow !== undefined; }The assumption is that the symbols will be defined only if the browser actually draws the shadow. This seems to be about right, the only exception I've found so far is the Webkit port to GTK (there's a bug report open).
Final point is Internet Explorer. As it turns out, there is a DropShadow filter. It's not terrible useful for this purpose, however. There are no soft edges, and it shadows the content rather than the containing box (it simply redraws the content with an offset in another color). So for my purpose I need to set a background color to ensure it's drawing a rectangle and not a text shadow. You could probably hack the lack of blurring with another filter, but in the end I went with a simple three-one-pixel-wide-lines approach that looks like my old hack but is much faster (updated, replaced the filter with a more appropriate one as suggested in the comments):
.shadowed { background-color: #fff; zoom: 1; filter: progid:DXImageTransform.Microsoft.Shadow(color='#969696', Direction=135, Strength=3); }This is served for IE only. The
zoom: 1
is a hack to ensure that the element gets a layout (to work around the usual IE 6 bug).So there you have it. Practical drop shadows. I will have to adjust the code a little bit as the other browsers get support, but I can live with that.