Drop shadow revisited, without float

Revisited as in “wait a minute, what if the methods for CSS drop shadow generally proposed on the web and in books by clique & all — Standards Village People — were just... convoluted ?” Yes, I have read CSS Mastery by Andy Budd & all.

I can’t criticize that book because it is a worthy effort at providing people with a collection of CSS tricks, the hippest ones at the time the book was written, and it probably is among the best CSS books ever published. All I’m asking is this : with regards to drop shadows have we overlooked a simpler solution ? Maybe not. Read along, please. I need your help.

The shadow is underneath

The idea behind all methods described in CSS Mastery is to apply a large drop shadow image (one with right and bottom gray edges) to the background of a wrapper div element.

The container element can be any block element — so it can be a paragraph as well.

If we apply a background-image to the wrapper div (or wrapper paragraph), we have to prevent that wrapper element from behaving like the block element that it is. We have to prevent it from stretching to its maximum width, beyond the width of the image. All methods cited in CSS Mastery resort to that trick : float the wrapper div to make it shrink-wrap around the image. The problem with floating the div is that it will disrupt the layout. I’ve had all sorts of problems with all methods described in CSS Mastery. The clagnut method was the simplest and it worked ; however, with it as well as with the others, I have to use an empty clearing paragraph (<p style="clear:both"></p>) beneath each paragraph that contains an image, if I do NOT want the text in the next paragraph to rise up and wrap around the image. And what about the line-height:0 used in that clagnut method, what does it ever do ? Does Andy Budd even know ?

Using a span for the wrapper element

REWIND. So, we don’t want the wrapping element to stretch to the full width of its parent. (That is the default behavior of a block element : if we don’t set the width of a block element, it will stretch out, horizontally, to fill whatever space is available.) But... why are we using a block element to wrap that image anyway ? Why not nest the image in an inline element instead ? Span it will be, the <span> element being an all-purpose inline element with no semantic meaning. We will style that span element : we’ll add to it the large background image with the drop shadow.

Here is the markup :

<span class="img-wrapper"><img src="picture.jpg" alt="[]" /></span>

We will add the background image to the wrapper span. If we want a shadow to appear either on the right or bottom or right and bottom of the image, we will position the background image so that its lower-right corner rests against the bottom and right edges of the wrapper element :

.img-wrapper {
background: url(images/shadow.png) no-repeat bottom right;

Light does not always come from the West and North, so this table gives us different background positioning based on where the light comes from.

ShadowCSS rule
Bottom & rightbackground: url(images/shadow.png) no-repeat bottom right;
Bottom & leftbackground: url(images/shadow.png) no-repeat bottom left;
Top & leftbackground: url(images/shadow.png) no-repeat top left;
Top & rightbackground: url(images/shadow.png) no-repeat top bottom;
Just bottombackground: url(images/shadow.png) no-repeat left bottom;
background: url(images/shadow.png) no-repeat center bottom;
background: url(images/shadow.png) no-repeat right bottom;

You get the idea. For this example, we will use the usual (common) light source : one that comes from the left and top, hence produces a shadow on the bottom and right sides of the image. Attached is a png image with a drop shadow on the right and bottom sides.

Now the drop shadow is covered by our image. It’s hidden. Time to reveal it. We will offset the image by a few pixels, that is, move that image relative to where it is now to a position that is a few pixels to the left and top.

Relative positioning does that. (Negative margins can produce similar results but were never intended to offset elements, so why make it more convoluted ?)

How does relative positioning work ? Unlike with absolute and fixed positioning, an element that is relatively positioned is still part of the rendering “flow” of the page, but at the very last moment, just before the element is displayed, it is offset from its position, leaving empty space behind. We specify the offset with these two CSS properties : top, left. If the element is to be offset by 5 pixels to the right, then the rule is left:5px. If the element is to be offset by 5 pixels to the left, then the rule is left:-5px.

Back to the CSS, we will move the image left-ward and higher up to reveal the shadow that it covers :

.img-wrapper {
background: url(images/shadow2.png) no-repeat bottom right;

.img-wrapper img {

Now if we want to add a white border to the image, we can add some padding with a white background :

.img-wrapper {
background: url(images/shadow2.png) no-repeat bottom right;

.img-wrapper img {
border:1px solid #a9a9a9;

The color of the border is of a light gray here.

What about adding a drop shadow to a block element ?

Say we want to add a drop shadow to a block of text so that it stands out. We have no other choice than to put our block of text inside a div (or any other block element), rather than a span. We can’t put a paragraph, a div, or any block element inside a span element, because an inline element may only contain other inline elements. The thing is, we might not want to be bothered with having to set a width for this wrapping div, so what do we do ? We will add a rule to the solution we previously came up with. We will tell the wrapper element to behave like an inline element after all. Even if it’s a block element — because we have to make it a block element, because it contains a block element, and we want our markup to validate. Unclear ? Let’s work it out a step at a time.

Here is our new markup :

<div class="img-wrapper"><p>This is very important text.</p></div>

This is valid xhtml. Now, in our stylesheet, we will tell the wrapper element to behave like an inline element, and we will modify our second selector so that it gets applied to div and paragraphs as well :

.img-wrapper {
background: url(images/shadow.png) no-repeat bottom right;

.img-wrapper img, .img-wrapper div, .img-wrapper p {

We’re done. With these additional lines, our CSS rules apply in more than one situation. With these changes, we can use any wrapper element (inline or block) and can add a drop shadow to an image, a div, or a paragraph. As long as the xhtml markup is valid of course.

Does that method work in all popular browsers ?

Actually... no. This non-float method works in IE, but does not work in Firefox. In Firefox, the background drop shadow image gets cropped. Not only that, it gets some default vertical offset. Even when the properties top and left are set to zero, the shadow is showing below the image. This offset adds up to the specified offset, producing a different result than the reliable one we get in Internet Explorer.

Screen shot in Firefox (Win)Note to Caroline : do not re-invent the wheel, just copy-and-paste CSS code that works, even if it does not totally make sense to you. Thou shalt not totally understand CSS and its mysterious ways. Trust The CSS gurus of the world, and don’t waste your time. And yet I am asking you : what is wrong with my understanding of CSS ? Can you help me with this, please ?

AttachmentSizeHitsLast download
drop-shadow.zip54.7 KB2311 years 37 weeks ago
Last edited by Caroline Schnapp about 12 years ago.

One file is attached to this posting. Login or register to download this file.


Thanks for nice technique.

I work with a large number of photos for our community. Since finding this technique, I plan to skip the step of placing a white border around each photo to make them look like a photograph. Thanks and by the way, It works in my version of Firefox and Safari for Windows.

Take Care,

I wrote this more than 1 year ago.

It's very possible that it works in my current version of Firefox, thanks for telling me, I'll have to check.

Rereading myself now, my head spins. Left-right-bottom-right-top-bottom-negative... argh! I have to read this again, and s l o w l y. I don't understand myself.


Ok. I just re-read my post. I understand. My explanation might be a little too verbose as us'al.

And yes the 'relative positioning' trick now works _also_ in Firefox :-)

desire good topic

After visiting your weblog, I have resolved my problem. Actually last week I have discuss with my friend on this baggy topic and we can not get any final decision. I will desire to read more things about it.

Good blog...

I like all the reviews have been posted by the visitors ofthis site ,some of them are very good suggested regard the article.
Kasino | betsson casino