Drop shadows. Web designers have loved them for a long time to the extent that we used to fake them with PNG images before CSS Level 3 formally introduced them to the spec as the box-shadow
property. I still reach for drop shadows often in my work because they add a nice texture in some contexts, like working with largely flat designs.
Not too long after box-shadow
was introduced, a working draft for CSS Filters surfaced and, with it, a method for drop-shadow()
that looks a lot like box-shadow
at first glance. However, the two are different and it’s worth comparing those differences.
For me, the primary difference came to light early on when I started working with box-shadow
. Here’s a simple triangle not unlike the one I made back then.
Let’s use this to break down the difference between the two.
Box Shadow
Add a box-shadow
on that bad boy and this happens.
It’s annoying, but makes sense. CSS uses a box model, where the element’s edges are bound in the shape of a rectangle. Even in cases where the shape of the element does not appear to be a box, the box is still there and that is was box-shadow
is applied to. This was my “ah-ha moment” when understanding the box in box-shadow
.
CSS Filter Drop Shadow
CSS Filters are pretty awesome. Take a gander at all the possibilities for adding visual filters on elements and marvel at how CSS suddenly starts doing a lot of things we used to have to mockup in Photoshop.
Filters are not bound to the box model. That means the outline of our triangle is recognized and the transparency around it is ignored so that the intended shape receives the shadow.
Deciding Which Method to Use
The answer is totally up to you. The simple example of a triangle above might make it seem that filter: drop-shadow()
is better, but it’s not a fair comparison of the benefits or even the possibilities of both methods. It’s merely an illustration of their different behaviors in a specific context.
Like most things in development, the answer of which method to use depends. Here’s a side-by-side comparison to help distinguish the two and when it might be best to choose one over the other.
Box Shadow | Drop Shadow | |
---|---|---|
Specification | CSS Backgrounds and Borders Module Level 3 | Filter Effects Module Level 1 |
Browser Support | Great | Good |
Supports Spread Radius | Yes, as an optional fourth value | No |
Blur Radius | Calculation is based on a pixel length | Calculation is based on the stdDeviation attribute of the SVG filter |
Supports inset shadows | Yes | No |
Performance | Not hardware accelerated | Hardware accelerated in browsers that support it. It’s a heavy lift without it. |
Wrapping Up
The difference between box-shadow
and filter: drop-shadow()
really boils down to the CSS box model. One sees it and the other disregards it. There are other differences that distinguish the two in terms of browser support, performance and such, but the way the two treat the box model is the key difference.
Update: Amelia identified another key difference in the comments where the spread of the radius for drop-shadow()
is calculated differently than box-shadow
and even that of text-shadow
. That means that the spread radius you might specify in box-shadow
is not one-to-one with the default spread value for drop-shadow
, so the two are not equal replacements of one another in some cases.
Let’s cap this off with a few other great examples illustrating that. Lennart Schoors also has a nice write-up with practical examples using tooltips and icons that we previously called out.
I really wish the Blur Radius matched between box-shadow and drop-shadow. The same blur amount in both yields different visual results.
A correction:
The
drop-shadow()
filter doesn’t take the fourth parameter for increasing spread—this isn’t just a browser support issue. From the spec:In this way, it is more like
text-shadow
thanbox-shadow
. It works by blurring and offsetting the existing graphic (already converted to pixels), not by generating a new, blurred box.And an extra warning:
The blur parameter to
drop-shadow()
isn’t equivalent to the one used intext-shadow
andbox-shadow
. Instead, it is a “standard deviation” value (equivalent to thestdDeviation
attribute in SVG filters), and is half the blur-radius used in the shadow properties.In other words,
filter: drop-shadow(0 0 30px #333)
is twice as blurry asbox-shadow: 0 0 30px #333;
.This discrepancy is really unfortunate, in my opinion, but all browser implementations of
drop-shadow()
are consistent, so the spec is unlikely to change it. (Discussion here)Thanks @AmeliaBR for the follow-up regarding the Blur discrepancy. I knew it was off, but didn’t realize it was by double/half.
Ah, thanks for the correction, Amelia! I have to admit that I was confused over the note about spread values in the official spec and the one in MDN. I corrected the information in the post.
Your warning is also spot on and made sure that is noted as well. :)
Cheers!
Geoff
LOL your picture is epic, “looking at the future of code”
Cool!
Just tried it. The only problem I should mention is that drop-shadow lacks antialiasing, on mobile it looks jagged if I zoom on it.
While it is true that the drop-shadow filter does not support multiple values comma separated, the css property filter does allow more than one filter in its value, and nothing prevents it from being the same type of filter with different values in its arguments.
I mean it’s possible to use drop-shadow() more than once in the same CSS declaration:
filter: drop-shadow(xxx) drop-shadow(zzz);
Thank you for including those old mine pens, Geoff.
Regards.
Good point. It reminds me you can stack box shadow too and people are using it to make 3D objects. The same is true for text-shadow. You can also apply box-shadow to :pseudo-elements reducing the extra markup. Hell, you can animate it too (animating things on :pseudo-elements wasn’t very consistant in the past but I guess it works now)!
You can see one of the demos here: http://blogs.sitepointstatic.com/examples/tech/css3-3d-text/index.html
The only remaining question is how heavy it is to render. Someone has to do the math to give you the answer.
Peace!
I have never before used drop-shadow() on filter property. It is a stunning discovering for me, so here is my first exploration : https://codepen.io/o-k-s-a-n-a/pen/oGroMv
I learned something today. Coo. Thank you, made my day.