293

I have a PNG image, that has free form (non square).

I need to apply drop-shadow effect to this image.

The standard approach ...

-o-box-shadow:      12px 12px 29px #555;
-icab-box-shadow:   12px 12px 29px #555;
-khtml-box-shadow:  12px 12px 29px #555;
-moz-box-shadow:    12px 12px 29px #555;
-webkit-box-shadow: 12px 12px 29px #555;
box-shadow:         12px 12px 29px #555;

... displays shadows for this image, like it is a square. So, I see my image and square shadow, that doesn't follows the form of object, displayed in image.

Is there any way to do it properly?

Kevin Ji
  • 10,479
  • 4
  • 40
  • 63
AntonAL
  • 16,692
  • 21
  • 80
  • 114

15 Answers15

358

Yes, it is possible using filter: dropShadow(x y blur? spread? color?), either in CSS or inline:

img {
  width: 150px;
  -webkit-filter: drop-shadow(5px 5px 5px #222);
  filter: drop-shadow(5px 5px 5px #222);
}
<img src="https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png">

<img src="https://cdn.freebiesupply.com/logos/large/2x/stackoverflow-com-logo-png-transparent.png" style="-webkit-filter: drop-shadow(5px 5px 5px #222); filter: drop-shadow(5px 5px 5px #222);">
Nino Filiu
  • 16,660
  • 11
  • 54
  • 84
Abdul
  • 3,739
  • 1
  • 12
  • 5
300

A little late to the party, but yes, it is totally possible to create "true" dynamic drop shadows around alpha masked PNGs, using a combination of dropshadow-filter (for Webkit), SVG (for Firefox) and DX filters for IE.

.shadowed {
    -webkit-filter: drop-shadow(12px 12px 25px rgba(0,0,0,0.5));
    filter: url(#drop-shadow);
    -ms-filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
    filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
}
<!-- HTML elements here -->

<svg height="0" xmlns="http://www.w3.org/2000/svg">
    <filter id="drop-shadow">
        <feGaussianBlur in="SourceAlpha" stdDeviation="4"/>
        <feOffset dx="12" dy="12" result="offsetblur"/>
        <feFlood flood-color="rgba(0,0,0,0.5)"/>
        <feComposite in2="offsetblur" operator="in"/>
        <feMerge>
            <feMergeNode/>
            <feMergeNode in="SourceGraphic"/>
        </feMerge>
    </filter>
</svg>

Some comparisons between true drop-shadow and box-shadow and an article on the technique I've just described.

starball
  • 20,030
  • 7
  • 43
  • 238
pushingphotons
  • 3,304
  • 1
  • 13
  • 7
  • 1
    Even more late to the party, but +1 for the cross-plateform CSS `filter` property... Though, I don't think HTML SVG tags be needed, any PNG with alpha channel will do the trick – mrcendre Jun 24 '13 at 04:46
  • 2
    Dudley Storey is right. Without the SVG, the shadow doesn't appear in Firefox. @AntonAL could accept this answer. – javsmo Oct 15 '13 at 21:22
  • 5
    DX filters no longer work on IE... Is there any new solution for IE? https://msdn.microsoft.com/en-us/library/hh801215(v=vs.85).aspx – tb11 Nov 18 '15 at 05:20
  • 3
    These days [Firefox supports](https://developer.mozilla.org/en-US/docs/Web/CSS/filter#drop-shadow%28%29_2) `filter: drop-shadow(x y blur color);` so the SVG trick should no longer be necessary. – Raptor007 Dec 11 '15 at 03:54
  • 15
    Can we not all just agree that IE should have been tossed into the garbage heap years ago? Edge is slightly better, but holy cow M$ did you purposefully set software development back to the dark ages with IE? What an abomination. – RyanNerd Aug 25 '16 at 05:38
71
img {
  -webkit-filter: drop-shadow(5px 5px 5px #222222);
  filter: drop-shadow(5px 5px 5px #222222);
}

That worked great for me. One thing to note tho in IE you need the full color (#222222) three characters don't work.

Ismail Farooq
  • 6,309
  • 1
  • 27
  • 47
Jaclyn U
  • 723
  • 5
  • 2
  • Not supporting three character colors is breaking CSS on purpose - what else do I need to check? Color names like `red`? Functions like `rgb()` and `rgba()` and `hsl()`? Constants like `transparent` and `currentColor`? Is it even case insensitive for `#20Beef`? IE version might be relevant, tho. – AmigoJack Feb 14 '21 at 00:38
37

If you have >100 images that you want to have drop shadows for, I would suggest using the command-line program ImageMagick. With this, you can apply shaped drop shadows to 100 images just by typing one command! For example:

for i in "*.png"; do convert $i '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage "shadow/$i"; done

The above (shell) command takes each .png file in the current directory, applies a drop shadow, and saves the result in the shadow/ directory. If you don't like the drop shadows generated, you can tweak the parameters a lot; start by looking at the documentation for shadows, and the general usage instructions have a lot of cool examples of things that can be done to images.

If you change your mind in the future about the look of the drop shadows - it's just one command to generate new images with different parameters :-)

psmears
  • 26,070
  • 4
  • 40
  • 48
  • 24
    While it's a solution, it does not answer the question! – leo Jun 13 '12 at 07:44
  • 6
    The asker is attempting to have the browser render the shadow, not execute scripts on the server that can create shadows. This is useful information but not the same problem space. – SG1 Aug 07 '13 at 20:47
  • Couple of notes to get this to work: 1. You need to create the shadow directory before running this command (such as with `mkdir shadow`) 2. `$i` should be quoted (as in `"$i"`) or it will choke if an image has a space in its filename: `for i in *.png; do convert "$i" '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage shadow/"$i".png; done` – Andrew Macheret May 23 '15 at 17:38
  • 2
    3. The resulting files will be named `filename.png.png`. Here's a fully working version: `for i in *.png; do convert "$i" '(' +clone -background black -shadow 80x3+3+3 ')' +swap -background none -layers merge +repage shadow/"$i"; done` – Andrew Macheret May 23 '15 at 18:07
  • @AndrewMacheret: Good points - though note this is meant to be an illustration of what can be done, rather than a fully working program! I've fixed the double .png suffix and the quotes; the directory thing I feel would just get in the way... – psmears May 25 '15 at 19:02
29

As Dudley mentioned in his answer this is possible with the drop-shadow CSS filter for webkit, SVG for Firefox and DirectX filters for Internet Explorer 9-.

One step further is to inline the SVG, eliminating the extra request:

.shadowed {
    -webkit-filter: drop-shadow(12px 12px 25px rgba(0,0,0,0.5));
    filter: url("data:image/svg+xml;utf8,<svg height='0' xmlns='http://www.w3.org/2000/svg'><filter id='drop-shadow'><feGaussianBlur in='SourceAlpha' stdDeviation='4'/><feOffset dx='12' dy='12' result='offsetblur'/><feFlood flood-color='rgba(0,0,0,0.5)'/><feComposite in2='offsetblur' operator='in'/><feMerge><feMergeNode/><feMergeNode in='SourceGraphic'/></feMerge></filter></svg>#drop-shadow");
    -ms-filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
    filter: "progid:DXImageTransform.Microsoft.Dropshadow(OffX=12, OffY=12, Color='#444')";
}
Community
  • 1
  • 1
Karl Horky
  • 4,410
  • 2
  • 31
  • 35
19

Add border with radius in you class if its a block. because by default shadow will apply on block border, even if your image have rounded corner.

border-radius: 4px;

change its border radius according to your you image corner. Hope this help.

anupal
  • 542
  • 1
  • 5
  • 8
17

Just add this:

-webkit-filter: drop-shadow(5px 5px 5px #fff);
 filter: drop-shadow(5px 5px 5px #fff); 

example:

<img class="home-tab-item-img" src="img/search.png"> 

.home-tab-item-img{
    -webkit-filter: drop-shadow(5px 5px 5px #fff);
     filter: drop-shadow(5px 5px 5px #fff); 
}
Mahmoud Zalt
  • 30,478
  • 7
  • 87
  • 83
8

Here is ready glow hover animation code snippet for this:

http://codepen.io/widhi_allan/pen/ltaCq

-webkit-filter: drop-shadow(0px 0px 0px rgba(255,255,255,0.80));
Dmitry Kaigorodov
  • 1,512
  • 18
  • 27
3

When i posted this originally it wasnt possible so this is the workaround. Now I simply suggest using other answers.

There is no way to get the outline of the image exactly but you can fake it with a div behind the image in the center.

If my trick doesn't work then you have to cut up the image and do it for every single of the little images. (the more images the more accurate the shadow will look) but for most images it looks alright with just one img.

what you need to do is to put a wrap div around your img like so

<div id="imgWrap">
    <img id="img" scr="imgLocation">
</div>

then you put an empty divider inside the wrap (this will serve as the shadow)

<div id="imgWrap">
    <div id="shadow"> </div>
    <img id="img" scr="imgLocation">
</div>

and then you have to make the shadow appear behind the img with CSS:

#img {
    z-index: 1;
}

#shadow {
    z-index: 0; /*make this value negative if doesnt work*/
    box-shadow: 0 -130px 180px 150px rgba(255, 255, 0, 0.6);
    width: 0;
    height: 0;
}

now position the imgWrap to position the original img... to center the shadow of the img you can mess with the first two values of the box-shadow making them negative.... or you can position the img and the shadow divs absolutely making img top and left values = 0 and the shadow div values = half of img width and height respectively.

If this looks horrid cut your img up and try again.

(If you don't want the shadow behind the img just on the outline then you need to make your img opaque and make it act as if it was transparent which is not that hard and you can comment and I'll explain later)

Xitcod13
  • 5,949
  • 9
  • 40
  • 81
2

In my case it had to work on modern mobile browsers, with a PNG image in different shapes and transparency. I created drop shadow using a duplicate of the image. That means I have two img elements of the same image, one on top of the other (using position: absolute), and the one behind has the following rules applied to it:

.image-shadow {
  filter: blur(10px) brightness(-100);
  -webkit-filter: blur(10px) brightness(-100);
  opacity: .5;
}

This includes brightness filter in order to darken the bottom image, and a blur filter in order to cast the smudgy effect drop shadow usually has. Opacity at 50% is then applied in order to soften it.

This can be applied cross browser using moz and ms flags.

Example: https://jsfiddle.net/5mLssm7o/

ROOT
  • 11,363
  • 5
  • 30
  • 45
ido
  • 811
  • 2
  • 8
  • 20
1

There's a proposed feature which you could use for arbitrarily shaped drop shadows. You could see it here, courtesy of Lea Verou:

http://www.netmagazine.com/features/hot-web-standards-css-blending-modes-and-filters-shadow-dom

Browser support is minimal, though.

avramov
  • 2,119
  • 2
  • 18
  • 41
1

A trick I often use when I just need "a little" shadow (read: contour must not be super-precise) is placing a DIV with a radial fill 100%-black-to-100%-transparent under the image. The CSS for the DIV looks something like:

.shadow320x320{    
        background: -moz-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%, rgba(0,0,0,0.58) 1%, rgba(0,0,0,0) 43%, rgba(0,0,0,0) 100%); /* FF3.6+ */
        background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%,rgba(0,0,0,0.58)), color-stop(1%,rgba(0,0,0,0.58)), color-stop(43%,rgba(0,0,0,0)), color-stop(100%,rgba(0,0,0,0))); /* Chrome,Safari4+ */
        background: -webkit-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* Chrome10+,Safari5.1+ */
        background: -o-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* Opera 12+ */
        background: -ms-radial-gradient(center, ellipse cover, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* IE10+ */
        background: radial-gradient(ellipse at center, rgba(0,0,0,0.58) 0%,rgba(0,0,0,0.58) 1%,rgba(0,0,0,0) 43%,rgba(0,0,0,0) 100%); /* W3C */
        filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#94000000', endColorstr='#00000000',GradientType=1 ); /* IE6-9 fallback on horizontal gradient */
  }

This will create a circular black faded-out 'dot' on a 320x320 DIV. If you scale the height or width of the DIV you get a corresponding oval. Very nice to create eg shadows under bottles or other cylinder-like shapes.

There is an absolute incredible, super-excellent tool to create CSS gradients here:

http://www.colorzilla.com/gradient-editor/

ps: Do a courtesy ad-click when you use it. (And, no,I'm not affiliated with it. But courtesy clicking should become a bit of a habit, especially for tool you use often... just sayin... since we're all working on the net...)

Rid Iculous
  • 3,696
  • 3
  • 23
  • 28
  • I could seen this looking quite nice when modified a little – BeachInCalifornia.com Apr 13 '14 at 01:11
  • 1
    “Courtesy ad-click”? Seriously, how is ripping off advertisers a good thing for the ’Net? Many of us *are* advertisers ourselves, or are paid by them, so triggering charges for advertisers for adverts for products you are never going to buy is a really unpleasant thing to do. If you are interested in an ad, click it by all means, but don’t do this! – al45tair Apr 15 '14 at 09:34
  • Oh, get off your moral high-ground, Alastair. The real-world looks a bit different. "Ripping off advertisers"? Really? LOL - Give me a break, man. I've been in advertising and marketing for nearly 30 years. To place the odd courtesy click has no influence whatsoever other than supporting the sites you use FOR FREE. If you're worried about inflation of prizes etc, worry about the increasingly monopolizing trends throughout the industry. *That's* what's distorting advertising prizes, not the odd courtesy click. – Rid Iculous Apr 17 '14 at 01:56
  • This looks horrible on FF and IE – barrypicker Nov 08 '16 at 17:45
1

Maybe you are in search of this. http://lineandpixel.com/blog/png-shadow

img { png-shadow: 5px 5px 5px #222; }
Iswanto San
  • 18,263
  • 13
  • 58
  • 79
Abhishek D
  • 63
  • 1
  • 2
  • 12
1

This won't be possible with css - an image is a square, and so the shadow would be the shadow of a square. The easiest way would be to use photoshop/gimp or any other image editor to apply the shadow like core draw.

prolink007
  • 33,872
  • 24
  • 117
  • 185
oezi
  • 51,017
  • 10
  • 98
  • 115
  • Thanks for reply. But, adding image in editor will have problems in the future, when i will have >100 images and should tweak shadows a little. T he best solution of my problem - is to add additional shadow image below each image in question with jQuery. – AntonAL Jul 06 '10 at 14:06
1

You can't do this reliably across all browsers. Microsoft no longer supports DX filters as of IE10+, so none of the solutions here work fully:

https://msdn.microsoft.com/en-us/library/hh801215(v=vs.85).aspx

The only property that works reliably across all browsers is box-shadow, and this just puts the border on your element (e.g. a div), resulting in a square border:

box-shadow: horizontalOffset verticalOffset blurDistance spreadDistance color inset;

e.g.

box-shadow: -2px 6px 12px 6px #CCCED0;

If you happen to have an image that is 'square' but with uniform rounded corners, the drop shadow works with border-radius, so you could always emulate the rounded corners of your image in your div.

Here's the Microsoft documentation for box-shadow:

https://msdn.microsoft.com/en-us/library/gg589484(v=vs.85).aspx

Chris Halcrow
  • 28,994
  • 18
  • 176
  • 206