The CSS drop-shadow() function applies a shadow effect to an element. Specifically, it creates a shadow around the element’s content shape, respecting its outline and transparency, so it comes in handy when we need a shadow effect around an irregularly-shaped element.
It is used with the filter and backdrop-filter properties, which allows us to apply varying visual effects, like blur(), grayscale(), sepia(), and yes, drop-shadow().
div {
background-color: #cdcdcd;
filter: drop-shadow(#301934 20px 10px 4px);
}
The drop-shadow() function is defined in the Filter Effects Module 1 specification.
The drop-shadow() syntax is similar to the box-shadow property you probably know about, but it only takes three length arguments (instead of four) and one color argument:
filter: drop-shadow(5px 5px 5px #cdcdcd);
Formally, it is declared as:
<drop-shadow()> = drop-shadow( [ <color>? && <length>{2,3} ] )
/* It can take a color along the two offsets */
filter: drop-shadow(#301934 20px 10px);
filter: drop-shadow(#301934 12px -12px);
filter: drop-shadow(#301934 -15px -5px);
/* We can add a blur radius */
filter: drop-shadow(#301934 15px 15px 5px);
/* The color can be at the end */
filter: drop-shadow(20px 10px 5px #301934);
The drop-shadow() function takes two parameters, which we can translate into two to four arguments. Let’s see how they look:
<color> (optional): The <color> parameter defines the color of the shadow effect around the element. If omitted, the value of the parent element’s color property is used.<length>: The <length> specifies the length of the shadow’s offset. It is divided into three arguments:
<offset-x>: is the length in the horizontal direction. It places the shadow on the right by default; however, a negative value reverses the effect’s direction to the left.<offset-y>: is the length in the vertical direction. It pushes the shadow towards the element’s bottom by default; however, a negative value places the shadow on top of the element.<standard-deviation>: This is a fancy name for a blur radius option. It defines the standard deviation of the Gaussian blur function. Unlike the other <length>arguments, it does not accept a negative value.The <length> parameter can take two or three values. If two values are taken, the browser uses them to define the <offset-x> and <offset-y> positions. The blur only comes in when all three lengths are used.
All we do is declare the filter property on an element and set the drop-shadow() function on it:
svg {
filter: drop-shadow(0 30px 30px #333);
}
You might already know that we can set multiple shadows on the box-shadow property for a longer, smoother looking shadow effect. All it takes is separating each shadow with a comma:
.box {
box-shadow:
0 2.8px 2.2px rgb(0 0 0 / 0.034),
0 6.7px 5.3px rgb(0 0 0 / 0.048),
0 12.5px 10px rgb(0 0 0 / 0.06),
0 22.3px 17.9px rgb(0 0 0 / 0.072),
0 41.8px 33.4px rgb(0 0 0 / 0.086),
0 100px 80px rgb(0 0 0 / 0.12);
}
Well, we can do the same with the drop-shadow() filter function, only without the commas:
.box {
filter:
drop-shadow(0 2.8px 2.2px rgb(0 0 0 / 0.034))
drop-shadow(0 6.7px 5.3px rgb(0 0 0 / 0.048))
drop-shadow(0 12.5px 10px rgb(0 0 0 / 0.06))
drop-shadow(0 22.3px 17.9px rgb(0 0 0 / 0.072))
drop-shadow(0 41.8px 33.4px rgb(0 0 0 / 0.086));
}
Here’s another example where you can toggle the shadow on and off:
This is a visual style that mimics old-school graphic designs, particularly from the 1970s and 80s. It uses the same layering technique we looked at earlier:
.retro-shadow {
filter:
drop-shadow(4px 4px 0px #ef4444)
drop-shadow(8px 8px 0px #3b82f6)
drop-shadow(12px 12px 0px #22c55e);
}
Notice that I’m setting the blur radius value to 0 in each drop shadow. This means the shadows don’t spread out but instead have sharp edges to them. The result is a sorta retro-looking design touch:
drop-shadow()Kevin Powell built a beating heart using the steps() function in one of his YouTube shorts, and I replicated it in the steps() entry. Here, I am trying out the heartbeat animation again, but this time with drop-shadow() radius blur to create a pulsing beat.
.pulsing-drop-shadow {
animation: pulse-drop-glow 2s infinite alternate;
}
@keyframes pulse-drop-glow {
from {
filter: drop-shadow(0 0 2px #ec4899);
}
to {
filter: drop-shadow(0 0 15px #ec4899);
}
}
drop-shadow() to box-shadow and text-shadowFor those of you keeping count, there are three ways to set shadows on things in CSS:
filter: drop-shadow()box-shadowtext-shadowWhy do we need all three? Well, first off, neither drop-shadow() nor box-shadow support text content. We need the text-shadow property specifically for that task.
But what about the other two? There’s a subtle but very important difference between drop-shadow and box-shadow and the clue is the “box” in box-shadow. The property merely applies a shadow around an element’s border box, which is always a square/rectangular shape, even if the element’s visual shape isn’t boxy. A classic example is setting box-shadow on an image:
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. See how drop-shadow() traces around the image’s transparent parts:
Another key difference is that 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.
How about a table that compares the three types of shadows side-by-side:
drop-shadow() | box-shadow | text-shadow | |
|---|---|---|---|
| How it works | Creates a shadow around the element’s alpha. | Creates a shadow around the element’s rectangular box. | Creates a shadow around text elements. |
| Spread radius? | No | Yes (optional) | No |
| Blur radius? | Yes | Yes | Yes |
| Uses | Any shape of element | Perfect for rectangular and square elements | Text elements |
| Hardware acceleration | In browsers that support it | No | No |
The CSS drop-shadow() function is defined in the Filter Effects Module 1 specification, which is currently in Editor’s Draft.
The CSS drop-shadow() filter function is supported by all major browsers.
.element { box-shadow: 0 3px 10px rgb(0 0 0 / 0.2); }
.element { backdrop-filter: blur(10px); }
.element { filter: blur(3px); }
p { text-shadow: 1px 1px 1px #000; }
.element { filter: blur(5px); }
.element { filter: brightness(1.5); }
.element { filter: grayscale(100%); }
.element { filter: hue-rotate(160deg); }
.element { filter: invert(0.8); }
.element { filter: opacity(50%); }
.element { background-image: url("https://example.com/image.png"); }