So for a couple of years now, folks have been trying to find ways to work around the fact that the box-shadow property from CSS3 seems to perpetually be just a few months away from actually appearing in Web browsers everywhere. Box shadows are a very common design element, and not being able to use them on the Web is a real pain in the ass.
You may have noticed that all block-style elements on this site include a very subtle shadow behind them. You can check out this post to see an example of what I’m talking about, and also to look at a picture of a really pretty girl. Two birds with one stone, I say.
I’ve been adding shadows to my art with the aid of a little Photoshop automation. When I’ve got a piece of art cropped and color-corrected the way I want it, I run a Photoshop action that adds a five-pixel border around the art, throws a very subtle shadow behind it, and comps the whole thing on top of my background color. It’s easy and fast.
But it would be even easier and even faster not to have to. Which is why I’d love to have something like the CSS box-shadow property. That way I could just tell my style sheet to throw a five-pixel white border around all my photos (with padding) and apply a shadow (with box-shadow). That’d be pretty awesome, in a nerdy sort of way. Especially when it comes to building sites for clients. It’s one thing for me to run all my art through Photoshop to apply the artistic elements; it’s another thing to tell a client they have to. So doing it all inside the site style sheet would be more than just a convenience there. It’s basically a necessity.
There are some techniques out there for doing shadows entirely with CSS, but they’re not really suitable for my purposes. See, all the techniques I know about rely on what we call a 315° shadow. That is, the notional light source is 45° counter-clockwise of vertical, which means the shadow appears below and to the right of the element that’s casting it. The only problem is, I don’t know anybody who’s really thought about it who thinks that kind of shadow looks good. The shadows I use on this site are 0° shadows, meaning they appear below and on both side of the object casting them, as if the notional light source were right above your screen. Existing CSS shadow techniques are totally unsuitable for creating shadows like those.
So I went to work concocting my own.
Here’s a sample image we’re going to use to construct our shadow. The way I look at it, if you’re going to spend a lot of time staring at a picture in order to get all the pixels around it to be just the right color in just the right places, it might as well be a picture you don’t mind staring at.
The first thing we need to do is put a white matte around the image. We do this with the padding property and the background property, like so:
img {
padding: 5px;
background: white;
}
The result looks like this:
Pretty good start. Now let’s get a shadow behind it. In order to do that, we’re going to start by breaking the shadow up into six pieces: the four corners, the left and right sides, and the bottom. We’ll deal with the bottom first, then the sides, and save the little fiddly bits in the corners for last. We’ll create an image that’s four pixels high and just one pixel across; that will let us stretch it horizontally to accommodate a picture of any width. If we add four pixels to the bottom padding, on top of the five pixels we’re using to create the white matte around the picture, then apply our four-pixel-high background image in a stripe across the bottom, we’ll get what we’re looking for. Translated into CSS, that looks like this:
img {
padding: 5px 5px 9px 5px
background: white url(shad_bottom.png) repeat-x bottom left;
}
That background property is a little tricky. What it says is that we want the background color to be white, for the matte, but we also want a background image to be applied. CSS lets you have both. The background image will start at the bottom left hand corner of the box (that’s that bottom left instruction there), and will stretch only across, not up (that’s repeat-x). When we apply that to our image, we get this:
That’s the bottom part of our shadow. Now we need to take care of the left and right sides. Because the sides are symmetrical and only two pixels wide, we can fake them with a border rather than having to apply another background image. This technique is going to end up being complicated enough as it is, so if we can keep the number of backgrounds to an absolute minimum, we’ll be thankful for it later. If we wrap our image in a div element — call it shadow — set that div’s background to the darker of the two shadow colors, put one pixel of padding on the left and right sides, then apply a one-pixel border on the left and right in our lighter color, that should just about do it. Translating all that into CSS gives us:
div.shadow {
background: #b4afa3;
padding: 0 1px;
border-left: 1px solid #dcd7c8;
border-right: 1px solid #dcd7c8;
}
Applied to our sample image, this is the result:
Not too shabby, huh? Of course … those corners could use some work. Come to think of it, those corners could use a lot of work. They kind of look like ass, especially the bottom ones. As you can see in this highly magnified view of our shadow, both the bottom and the top corners are nicely fuzzed. We need to apply those fuzzy corners to our picture.

We’ll start with the bottom-left corner. In anticipation of this eventuality, I used Photoshop to prepare four very small image files, one for each corner. The bottom corners are four pixels square, and the top corners are four pixels high by two across. Getting the first of them, the bottom-left corner, into place is a simple matter of absolute positioning. We’ll add a div inside our shadow div, adjacent to our img element. We’ll call it bottomleft for all the obvious reasons. Its style definition will look like this:
div.bottomleft {
width: 4px;
height: 4px;
background: url(shad_blcorner.png) no-repeat bottom left;
position: absolute;
bottom: 0px;
left: -1px;
}
That left property is a bit of a cheat. See, the outer row of pixels on the left-hand side of our picture is formed by the border, and the border is technically outside the content area of the object. If we just tell the corner image to appear at coordinate zero, it actually shows up one pixel too far inside. So we nudge it back out.
Here’s how the bottom-left corner looks when applied. Note particularly how the bottom-left corner looks compared to the bottom-right corner. Big difference, huh? Okay, well, technically it’s not a big difference, but once you know where to look, the difference is pretty remarkable.
Adding the bottom right corner is easy. We just flip-flop the positioning.
div.bottomright {
width: 4px;
height: 4px;
background: url(shad_brcorner.png) no-repeat bottom right;
position: absolute;
bottom: 0px;
right: -1px;
}
The result:
Now all that’s left are the top corners. Unsurprisingly, we deal with them just as we dealt with the bottom corners.
div.topleft {
width: 2px;
height: 4px;
background: url(shad_tlcorner.png) no-repeat top left;
position: absolute;
top: 0px;
left: -1px;
}
div.topright {
width: 2px;
height: 4px;
background: url(shad_ttcorner.png) no-repeat top right;
position: absolute;
top: 0px;
right: -1px;
}
Like so:
And there it is. A matte plus 0° drop shadow constructed entirely with CSS. And believe it or not, it even works in Microsoft Internet Explorer. Though not without a whole lot of massaging on my part. God, what a piece of crap that thing is. If you’re one of the three or four indigenous people of Arctic Finland who still uses it, for God’s sake, stop. Firefox is really iffy in a whole lot of ways, but for basic Web surfing, it beats the pants off of Internet Explorer. [I think that’s what they call damning with faint praise. —Ed.]
So how does our CSS shadow compare to a Photoshop-applied shadow? Well, let’s do a side-by-side taste test and see.
The picture on the left has a CSS matte and a CSS shadow on it. The picture on the right has a matte and a shadow that were applied in Photoshop. Or maybe it’s the other way around. I forget. Point is, the two pictures are pixel-for-pixel identical. (There may be some very minor color differences between the two depending on whether your computer is correctly configured for color management support. Most aren’t. But the differences will be small.) The one on the left is a heck of a lot smaller, too: 20 kilobytes versus 76 kilobytes for the one on the right. So it’s not just more convenient; it’s more efficient, too.
It would be unfair of me to describe this technique without calling attention to its one most significant drawback: The markup required to assign all those shadow elements to an image is pretty darned ugly. We’re talking about, in addition to just the plain old img element, an enclosing div plus four additional divs to handle the corners. You’re looking at something like this:
<div class="shadow">
<img src="shufflegirl.jpg">
<div class="topleft"></div>
<div class="topright"></div>
<div class="bottomleft"></div>
<div class="bottomright"></div>
</div>
And that’s for just one picture. Of course, we’re still a long way from the bad old days of table-based page layout, but using CSS shadows is definitely a compromise between spending more time in Photoshop and having to write uglier markup. It’s up to you to decide which one of those things annoys you more, and act accordingly.
I’ve assembled a little demo of this technique that you can download and use on your own sites if you want. It includes a HTML file (valid XHTML 1.0 Transitional), a style sheet (also valid), a sample photo (taken by yours truly) and the five PNG images you’ll need for creating shadows on a white background. Also included, at no extra charge, is an ImageReady file that you can use to create your own shadow component files by changing the color of the background layer. You can download the demo here.
11/30/05 1:36:03 PM
A reader from Nassau, Bahamas, writes to point out that, at least in theory, it should be possible to create the four corner objects using JavaScript and the Document Object Model programming interface. JavaScript has never been my thing, so I don’t know whether such a trick would definitely be possible or not, but at least as an idea is sounds plausible. Maybe I’ll dig into the possibilities and post a follow-up later in the week.

Comments
All comments are the property of their owners and do not reflect the opinions of this Web site or, well, basically anybody at all. The author of this Web site reserves the right to edit the hell out of any and all comments. Participate at your own risk.
Javascript, CSS, DOM, HDTV, LCD Monitor madness, Deals, Domains and Brain Fragmentation
Top 10 custom Javascript functions of all time- A pretty good list of essential DOM related javascript functions. Please note the functions are mostly DOM related. Speaking of Javascript - (AJAX) XmlHttpRequest Insanity Solution- Cross-domain requests …
techThoughts Presented By Benjamin Bach
Wednesday, November 30th, 2005, 2:29 pm
Shadow Warngling ( Or How I hacked Someone Elses Hard Work!)
Im currently reading (albeit very slowly!) Dom Scripting, a great book by Jeremy Keith from Clear:Left on , well, scripting the DOM. Not my favourite subject, being a lowly psuedo-geek, but the book is written in English, so I̵…
Nothing to See. Move Along
Wednesday, November 30th, 2005, 9:52 pm
Another contribution to CSS Drop shadows
Digging “My contribution to the CSS shadow kerfuffle” I had the same thought as “Bahamas” about javascript, so I googled a little and came up with this helpful site. Adapting brieflt, I have come up with a nice way to…
hounddog32
Thursday, December 1st, 2005, 7:37 am
Url Css
From: Katharine css ");, , , Re: Intro and question - CSS Zengard
Url Css
Tuesday, February 20th, 2007, 7:09 am
[…] CSS Shadows - So for a couple of years now, folks have been trying to find ways to work around the fact that the box-shadow property from CSS3 seems to perpetually be just a few months away from actually appearing in Web browsers everywhere. Box shadows are a very common design element, and not being able to use them on the Web is a real pain in the ass […]
Web design Snippets I can’t Live without | Flawless Mind
Friday, April 13th, 2007, 5:45 am
谢谢. [Thank you.]
Kevin
Tuesday, April 17th, 2007, 9:33 am
很棒的教程!非常感谢! [Very good lesson! Thank you very much!]
CodeBit.cn
Tuesday, April 24th, 2007, 9:01 am
Great. Por lo general siempre he tenido problemas con esta técnica pero creo que ya está claro.
Christian
Tuesday, April 24th, 2007, 2:55 pm
klasse sache - gratulation zu dieser hilfreichen idee
great stuff - congratulations for this helpfull idea
have fun - paby
paby
Thursday, April 26th, 2007, 5:29 am
受益匪淺 ,謝謝 {Thanks}
Jseven.cn
Monday, May 7th, 2007, 8:51 am
El ejemplo es muy bueno me a solucionado muchos problemas.
Agradezco al autor de este tutorial es muy bueno.
Emiliano Jesus Diaz Larez (Venezuela)
Wednesday, May 9th, 2007, 3:19 pm
came across your site while browsing. I was using my works computor ie5.5000 implimented and your site collapses. The shadow example doesn’t work either. Sounds like a moan but I learn CSS by reading ‘others stuff’ and am greatful for the ideas and so on. THouhgt you might like to know that (I’m assusming it is a IE 5.5000 thing) your site is not being viewed maybe as it should be. I’ve used my home email address wehich ytou can reply to. I’ve also done a couple of screen dumps should you want to ‘see what I see’.
Regards
please do not pass the email address around thank you.
raymond.howell
Wednesday, May 16th, 2007, 11:50 am
Niezla lekcja,
mempty
Sunday, May 20th, 2007, 6:18 pm
cool, thank you very much!
cssyeah
Thursday, May 24th, 2007, 12:15 am
Интерестноя стотья,и главное полезно для тех кто только начинает свое развитие в веб дизайне.спасибо.
blek
Thursday, May 24th, 2007, 12:12 pm
come on, using 4 subdivs is not really the best way to achieve shadows. is it anyone using this technique anyway?
guest
Friday, May 25th, 2007, 3:18 am
img {
padding: 5px;
background: white;
}
how can this work??
amanin
Saturday, May 26th, 2007, 6:33 pm
Thank you! I was googling and googling … and finally I found the solution on your page!
Greetings
Felix
Felix
Sunday, May 27th, 2007, 7:07 am
Hey, this is better than any other “solution” I’ve seen out there for drop shadows. Who cares about all the div’s?? But no, I have to have “pretty” code. Shut the &%$# up whomever that Guest is that complained about the div’s.
Coby
Thursday, May 31st, 2007, 2:11 pm
I have been looking around for a good answer for this. Personally I would have tried to set the shadow as one whole picture and float the other image ontop with z index just set the margins and voila.
Unfortunately does not help myself, as I want to add a shadow to a image/text box and I dont want it looking funny if someone should change the text size on the page thus expanding the text box. Any ideas?
Charles
Saturday, June 2nd, 2007, 11:39 am
谢 谢 ! {thanks}
ANDY
Thursday, June 7th, 2007, 2:50 am
看不大懂英文,郁闷.[my english is very bad!]
jonly
Monday, June 11th, 2007, 3:03 am
Your drop shadows are nice. However, I felt your rant on IE was the result of ignorance. What you did required far more coding and time than a single DIV drop chadow can do in IE. You see, to do in another browser what can be done in IE for drop shadows requires more all those DIV’s you used. This can be accomplished in IE with 1 DIV. Just one, and you cannot tell the difference with your eyes unless the div is HUGE. The truth is, IE suppots more WC3 standard content and commands, and supports them better, than any other browser. I can make a drop shadow for IE that requires a fraction of the time and code as these bloated examples, and you will not be able to tell the difference with your eyes. That’s right! IE is also far more lenient with errors because it’s error correcting is far more intelligent. Don’t believe me? Find a web site with lots of errors. Look at it withe Firefox or any other browser. Ugh! Then look at it with IE. Hmmm. Notice the magic. Miraculously most of the errors seem to dissaper! Now, while this may not be an excuse for anyone making a site full of errors, you get the point. Got to WC3 and look at the comparison charts. Hmmm. Gosh. It looks like IE supports far more things than any other browser. Well whaddya know.
I realuize it’s fashionable, especially for the young croud to hate Microsoft salaciously. I’m not fond of them either. But this kind of ranting is the result of ignorance or spite, I know not which. It has no place in professional web design etiher. it just makes your site look amatuerish. Oh, and ignorant, since professional web designers know that IE has better support than any other browser. Almost forgot that part.
It only takes one div to shadow an image in IE.
Matt
Saturday, June 16th, 2007, 2:06 pm
Kara, isso ai é muito legal!! CSS é tudo de bom!! Quem não usa, não sabe o que está perdendo!!!
Pedro Linhares
Saturday, June 16th, 2007, 8:21 pm
Well said Matt
The Doc
Monday, June 18th, 2007, 9:42 pm
No, not well said. Look at the date on this article. It’s nearly two years old, and was written a full year before IE 7 came out.
Keflex
Monday, June 18th, 2007, 11:10 pm
Plus he obviously doesn’t do very much web designing if that is his opinion..
JoMilla
Tuesday, June 26th, 2007, 6:51 pm
Thanks for sharing the code. I can finally make my pics look like i wanted on my web pages.
Regards: George Britton
George Britton
Sunday, July 1st, 2007, 11:47 pm
Hello,
Very nice approach to a problem that I’m sure has had a lot of people stumped for a while now. One question I have is regarding the use of this code in a CMS such as Drupal or Joomla. I’m not sure why, but whenever I try this method in one of these sites I see the bottom shadow getting replaced like 2 and 1/2 times.. Also there is a light grey strip added as well. I’ve tried this with multiple themes and I’m wondering if it’s not a float issue due to being inside a div?
Has anyone else encoutered this problem? It’s only the bottom; the sides look great and the bottom is working.. it just has extra stuff added on the bottom.
Todd
Friday, July 6th, 2007, 2:32 am
Hi, this is just what i was looking for. Im a beginner at CSS, so i have an easy question. I guess the shadow files need to be browesed to the right folder, but i cant seem to brows them in any way. I think ive done the right things with the codes but its not getting shadowed. Thanks for the help : )
Chris
Monday, July 9th, 2007, 6:56 pm
One of the best sites on the internet, if you interested in css.
Nice done!
Jimmy
Thursday, July 26th, 2007, 8:07 am
Looks great visually, but the markup makes this almost a completely pointless exercise… well for me :¬)
It is nice work still, I guess once you have been doing this stuff for a while you really do see the pro’s and con’s of ‘stuff’… mainly markup… your html markup, and keeping it seperated from the design…
Matt: Ie6 blows goats, hard, like all day long, sure it ‘supports’ more (i dunno wtf your talking about cuase it is missing a shed load of pseudo selectors) but I know for fact it sucks at doing any of these things correctly… I hate microsoft… their ignorance breeds hatred… bigtime… money grabbing etc… :¬)
Always a critic
Tuesday, August 7th, 2007, 6:39 am
Thank you very much. Helped me a lot:-)
Florian
Monday, August 20th, 2007, 5:50 pm
[…] CSS shadow […]
Webdesign Tips deel 2
Saturday, August 25th, 2007, 3:18 pm
Can’t you sum this all up in to one set of code.
adrian
Monday, August 27th, 2007, 9:33 pm
Спасибо, очень интересно!!!
DEW
Thursday, August 30th, 2007, 4:23 pm
just fantastic….
bill
Sunday, September 9th, 2007, 8:59 am
[…] http://theshapeofdays.com/2005/11/29/my-contribution-to-the-css-shadow-kerfuffle.html […]
CSS ile Gölge
Thursday, September 20th, 2007, 6:47 am
Very nice tutorial. But your tutorial have several flaws. Your technique will fail in IE5 or IE6 since it does not support png alpha channel. Also CSS seems to be little lengthier than what it supposed to be or could be.
Nicholas
Friday, September 28th, 2007, 5:44 pm
[…] The Shape of Days: My contribution to the CSS shadow kerfuffle […]
All Night Coder - Today’s Top Blog Posts on Programming - Powered by SocialRank
Monday, October 1st, 2007, 5:06 am
Thanks very much~~
wskyygy
Monday, October 8th, 2007, 10:15 pm
[…] die von einem User integriert werden, sollen einen hbschen Rahmen bekommen, so wie hier: The Shape of Days: My contribution to the CSS shadow kerfuffle Dazu ist es ntig, dass ich um Bilder ein <div>-Tag setze (siehe Artikel). Leider wei ich […]
Wie eine neue Definition in einem Template anlegen? - XHTMLforum
Thursday, October 11th, 2007, 10:45 am
This is amazing!
stephanie
Sunday, October 21st, 2007, 12:28 pm
this is so nice.
vijay a. solanki
Tuesday, November 6th, 2007, 2:49 am
Jeff, this is the best boxshadow solution available on the Internet. And I should know, because I’ve looked at every Web site on the Internet.
I’ll admit did struggle with it a bit until I realized, for me, at least, your boxshadow code requires the XHTML 1.0 Transitional DOCTYPE (which you’ve noted on this page) to properly display in FF.
Thanks!
kturet
Wednesday, November 14th, 2007, 10:56 pm
[…] Harrell 的大作 “My contribution to the CSS shadow kerfuffle”后开始实践。下载所需图片,复制文中的代码后,效果如此。 用IE […]
net2e » Blog Archive » 用css生成投影效果(兼容FF,IE)
Monday, November 19th, 2007, 11:52 am
[…] Harrell的大作 "My contribution to the CSS shadow kerfuffle" […]
net2e » Blog Archive » 用css生成投影效果(兼容FF,IE)
Wednesday, November 21st, 2007, 6:02 am
Seems like it would be easier to just apply the shadow to the pic itself.
Someone
Monday, December 17th, 2007, 1:51 pm
Yes, it is easier. But, if you read the article you will see that the problem is making the shadows on images without editing.
NeonDragon
Thursday, December 20th, 2007, 2:43 pm
wo wo wo this is very nice!!!!!!!!!!!!!!
arman
Tuesday, January 1st, 2008, 3:45 am
I created an online tool that generates the HTML to display CSS shadows. Initially, the tool was made specifically to unit-test my image shadow routine. You could also download the PHP code to generate shadows wherever you need.
One nice thing about my code is that it requires no images or javascript. The colors are calculated for the various div layers based on your start and ending colors, as well as the # of colors.
I hope this helps somebody.
Brian Gillingham
Sunday, January 13th, 2008, 7:37 pm
sehr schön - Thank you
Anonymous
Tuesday, January 29th, 2008, 7:31 am
hey
the shadow effect is great. thanks.
krupa
Wednesday, January 30th, 2008, 6:28 am
Nice tut, thanks so much.
Can you tell me who is she. She so cute :D
Nguyễn
Friday, February 1st, 2008, 3:12 am
wow. thanks for the tip. this is nice. ^^
distrust
Wednesday, February 6th, 2008, 1:02 pm
Brilliant! thanks mate.
Andersson
Thursday, February 14th, 2008, 2:57 pm
Never seen such a great css-shadow tutorial! Great work my friend!
Thanks a lot!
Matthias N.
Sunday, February 24th, 2008, 11:34 am
Thank you for sharing the code. I appreciate your time and thoughts, the download was perfect.
Leisha Kruger
Tuesday, February 26th, 2008, 9:30 pm
Hi jeff I’m studying CSS at college here in glasgow Scotland and I’m looking for straight forward css solutions that can be applied without too much fuss. Thanks for supplying such a good one for an important design matter. Like your taste in pretty girls, … we’re not all just nerds you know girls!
Mike Riches
Saturday, March 8th, 2008, 5:46 pm
Still the best image shadow solution on the web. This is just perfect! Thanks!
Alex
Wednesday, March 12th, 2008, 9:00 pm
Nice work! It would be sweet to provide links to the images used for the shadows, too.
roger pack
Saturday, March 29th, 2008, 12:12 pm
Wow! very nice. Thanks for sharing it to us :)
dreamluverz
Tuesday, April 1st, 2008, 9:39 am
Never seen such a great css-shadow tutorial!
Dhanasekar
Saturday, April 26th, 2008, 11:37 am
太棒了bravo! 谢谢thank u very much!:)
but i think i’d better not use this, ‘cause .png is not supported by ie6 and my websites are offen browsed by ie6.
CHEN
Wednesday, April 30th, 2008, 2:13 pm
Thanks! Note also that if you mess around a lot with position:relative and put your bottom corners after your main picture, you can have shadows that follow your divs anywhere :)
roger pack
Wednesday, April 30th, 2008, 8:19 pm
Спасибо, очень познавательно и интересно. Good work, thanks!!!
pergam
Monday, May 5th, 2008, 2:12 am
not bad
praveen
Wednesday, May 7th, 2008, 11:08 pm
Спасибо!!!!
Glamour
Sunday, May 11th, 2008, 7:22 am
Ummm…the only problem with this solution is that it takes two seconds to do this in Photoshop and a half hour in CSS.
Mike Pereira
Wednesday, May 21st, 2008, 9:35 am
thats usefull, thanks
Johnny
Saturday, May 24th, 2008, 10:37 am
很好, ,受用。 学习中。
z.Yleo77
Monday, May 26th, 2008, 5:38 am
Pretty good! thanks i need to learn more.
Andy.s
Thursday, June 12th, 2008, 8:55 pm