What is CSS drop-shadow, exactly?

In CSS, “drop shadow” usually means the filter: drop-shadow(...) function. It’s a shadow that’s computed from the visible pixels of an element (think: “shadow of the silhouette”), which makes it perfect for transparent PNGs, SVGs, and weird-shaped things.

That’s different from box-shadow, which shadows the element’s box (rectangle + border radius). Box shadows are amazing… but they can’t “follow” the transparent shape inside a PNG.

drop-shadow() syntax and the mental model

The function looks like this:

filter: drop-shadow(x-offset y-offset blur-radius color);

  • x-offset moves the shadow left/right (negative values go left).
  • y-offset moves the shadow up/down (negative values go up).
  • blur-radius softens the shadow (0px is crisp).
  • color can be named, hex, rgb(), rgba(), hsl(), etc.

The key idea: drop-shadow uses the element’s rendered pixels as a mask. If your image has transparent areas, the shadow respects them.

.sticker {
  filter: drop-shadow(0px 16px 18px rgba(0, 0, 0, 0.35));
}
  
.sticker {
  filter: drop-shadow(18px 8px 10px rgba(0, 0, 0, 0.28));
}
  
.sticker {
  filter: drop-shadow(-14px 10px 6px rgba(0, 0, 0, 0.22));
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  min-height: 320px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f4f5f7;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.sticker {
  width: 260px;
  height: auto;
  display: block;
}
  
Semi transparent PNG for drop shadow demo

CSS drop-shadow vs box-shadow

Here’s the practical difference you’ll feel immediately:

  • box-shadow shadows the element’s box (rectangle / border-radius). Great for cards, buttons, panels.
  • filter: drop-shadow() shadows the element’s visible pixels (silhouette). Great for PNGs with transparency, SVG icons, cut-out shapes.

Let’s compare them on a transparent PNG. Notice how box-shadow looks like a “shadowed rectangle”, while drop-shadow() hugs the actual object.

.photo {
  box-shadow: 0px 18px 22px rgba(0, 0, 0, 0.28);
}
  
.photo {
  filter: drop-shadow(0px 18px 22px rgba(0, 0, 0, 0.28));
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.grid {
  min-height: 360px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f3f4f6;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.card {
  width: min(520px, 92vw);
  background: #ffffff;
  border: 1px solid #e7e7e7;
  border-radius: 18px;
  padding: 18px;
}

h3 {
  margin: 0 0 10px 0;
  font-size: 16px;
}

.photo {
  width: 280px;
  height: auto;
  display: block;
  margin: 0 auto;
}
  

Same PNG, different shadow technique

Transparent PNG fruit demo

When to use which

  • Use box-shadow for UI surfaces (cards, modals, buttons). It’s fast, predictable, and has a spread parameter.
  • Use drop-shadow() when the element’s silhouette matters (transparent PNGs, SVG icons, irregular shapes).

Learn more about box-shadow in the CSS Box Shadow Interactive Tutorial.

Tuning the three main knobs: offset, blur, color

Most “good shadows” are just a nice combination of: a small vertical offset, a moderate blur, and a semi-transparent color. Let’s make those values interactive with range sliders.

This playground controls the numeric values inside drop-shadow(x y blur color).

.hero-img {
  filter: drop-shadow(0px 16px 22px rgba(0, 0, 0, 0.30));
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.scene {
  min-height: 380px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: radial-gradient(circle at 30% 20%, #ffffff 0%, #f2f3f6 55%, #e9ebf0 100%);
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.hero {
  width: min(560px, 94vw);
  background: #ffffff;
  border: 1px solid #e6e6e6;
  border-radius: 20px;
  padding: 18px;
}

.hero h4 {
  margin: 0 0 12px 0;
  font-size: 16px;
}

.hero-img {
  width: 300px;
  height: auto;
  display: block;
  margin: 6px auto 0 auto;
}
  

Drag the sliders: offset + blur

Dahlia PNG demo

Quick beginner guidelines

  • A natural “floating” shadow is often more blur than offset.
  • If the shadow looks dirty, reduce blur or reduce alpha (opacity).
  • If the shadow looks like it’s detached, reduce the offset a bit.

CSS drop-shadow opacity

There are two common ways to control drop-shadow opacity:

  1. Set alpha in the shadow color (recommended): rgba(0, 0, 0, 0.35).
  2. Make the whole element semi-transparent (usually not what you want): opacity: 0.7. That fades the element itself too.

Let’s compare. One snippet changes the shadow alpha, the other fades the entire element.

.demo-img {
  filter: drop-shadow(0px 18px 22px rgba(0, 0, 0, 0.12));
}
  
.demo-img {
  filter: drop-shadow(0px 18px 22px rgba(0, 0, 0, 0.42));
}
  
.demo-img {
  filter: drop-shadow(0px 18px 22px rgba(0, 0, 0, 0.30));
  opacity: 0.65;
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  min-height: 380px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f4f5f7;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.panel {
  width: min(560px, 94vw);
  background: #ffffff;
  border: 1px solid #e6e6e6;
  border-radius: 18px;
  padding: 18px;
}

.panel p {
  margin: 0 0 12px 0;
  font-size: 14px;
  line-height: 1.4;
}

.demo-img {
  width: 280px;
  height: auto;
  display: block;
  margin: 0 auto;
}
  

Compare: low alpha shadow, high alpha shadow, and opacity on the element.

PNG opacity comparison demo

CSS drop-shadow spread (the honest truth)

drop-shadow() does not have a spread parameter. If you’re coming from box-shadow, this feels like, “Wait… where’s my spread slider?” Yep. That’s the trade-off.

Why there’s no spread

box-shadow draws a shadow for a box shape, and it can expand/shrink that shape (spread). drop-shadow() is based on the element’s pixels, so “spreading” the silhouette is not part of its basic model.

Spread workarounds you can actually use

  • Stack multiple drop-shadows: one tight, one blurrier. This can feel like “spread + blur”.
  • Use an SVG filter if you truly need morphological expansion (advanced, but possible).
  • Fake an outline glow by using several drop-shadows at different offsets (looks like thickness).

Let’s do the most common workaround: stacking two drop-shadows.

.cutout {
  filter: drop-shadow(0px 10px 10px rgba(0, 0, 0, 0.25));
}
  
.cutout {
  filter:
    drop-shadow(0px 10px 10px rgba(0, 0, 0, 0.18))
    drop-shadow(0px 26px 26px rgba(0, 0, 0, 0.14));
}
  
.cutout {
  filter:
    drop-shadow(0px 8px 0px rgba(0, 0, 0, 0.12))
    drop-shadow(0px 20px 22px rgba(0, 0, 0, 0.16));
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.canvas {
  min-height: 380px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f1f2f4;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.box {
  width: min(560px, 94vw);
  background: #ffffff;
  border: 1px solid #e6e6e6;
  border-radius: 18px;
  padding: 18px;
}

.box p {
  margin: 0 0 12px 0;
  font-size: 14px;
  line-height: 1.4;
}

.cutout {
  width: 290px;
  height: auto;
  display: block;
  margin: 0 auto;
}
  

Single shadow vs stacked shadows (often the easiest “spread-ish” trick).

Stacked drop shadows demo

CSS drop shadow text

There are two main ways to shadow text:

  • text-shadow: built for text, very common, very controllable.
  • filter: drop-shadow() on the element: shadows the rendered pixels of the text, which can look slightly different (and can apply to more than just glyphs if the element also contains icons).

Beginners tip: start with text-shadow. Use drop-shadow() on text when you want the effect to match other drop-shadowed elements, or you want to shadow the “whole rendered thing” (text + inline SVG).

.title {
  text-shadow: 0px 10px 18px rgba(0, 0, 0, 0.30);
}
  
.title {
  filter: drop-shadow(0px 10px 18px rgba(0, 0, 0, 0.30));
}
  
.title {
  text-shadow:
    0px 8px 12px rgba(0, 0, 0, 0.22),
    0px 18px 26px rgba(0, 0, 0, 0.16);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.hero {
  min-height: 360px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: radial-gradient(circle at 40% 30%, #ffffff 0%, #f2f3f6 45%, #e9ebf0 100%);
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.card {
  width: min(760px, 94vw);
  background: #ffffff;
  border: 1px solid #e6e6e6;
  border-radius: 20px;
  padding: 26px;
}

.title {
  margin: 0;
  font-size: clamp(34px, 5vw, 46px);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.sub {
  margin: 12px 0 0 0;
  font-size: 14px;
  opacity: 0.8;
}
  

Soft Drop Shadow Text

Compare text-shadow vs filter: drop-shadow(), then a stacked text-shadow.

Learn more about text-shadow in the CSS Text Shadow Interactive Tutorial.

A practical pattern: text shadow for readability

If text sits on a busy background, a small shadow can increase readability. Keep it soft and low-opacity so it feels like depth, not a cartoon outline.

Multiple drop-shadows: glows and “outline-ish” looks

Just like multiple box-shadow layers, you can stack multiple drop-shadow() functions by writing them one after another in filter.

This is how you get glows, richer depth, or a faux outline around transparent artwork.

.icon {
  filter:
    drop-shadow(0px 10px 14px rgba(0, 0, 0, 0.22))
    drop-shadow(0px 26px 30px rgba(0, 0, 0, 0.14));
}
  
.icon {
  filter:
    drop-shadow(0px 0px 14px rgba(40, 140, 255, 0.40))
    drop-shadow(0px 0px 30px rgba(40, 140, 255, 0.22))
    drop-shadow(0px 18px 22px rgba(0, 0, 0, 0.18));
}
  
.icon {
  filter:
    drop-shadow(0px 0px 0px rgba(0, 0, 0, 0.00))
    drop-shadow(0px 0px 2px rgba(0, 0, 0, 0.30))
    drop-shadow(0px 0px 2px rgba(0, 0, 0, 0.30))
    drop-shadow(0px 18px 22px rgba(0, 0, 0, 0.16));
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  min-height: 380px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #0f172a;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.shell {
  width: min(760px, 94vw);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 20px;
  padding: 18px;
  color: rgba(255, 255, 255, 0.88);
}

.shell p {
  margin: 0 0 12px 0;
  font-size: 14px;
  line-height: 1.4;
}

.icon {
  width: 280px;
  height: auto;
  display: block;
  margin: 0 auto;
}
  

Stacked drop-shadows: depth, glow, and an outline-ish trick.

PNG glow and outline demo

Common pitfalls and gotchas

1) drop-shadow can expand the visual bounds

Shadows paint outside the element. That’s normal. But if a parent has overflow: hidden, your shadow might get clipped. If your shadow “mysteriously disappears,” check for overflow.

2) drop-shadow is applied after rendering

Because it’s a filter, it applies to the rendered result. That’s awesome (silhouette shadows), but it also means it can be a bit more expensive than simple box shadows if you go overboard. Use multiple layers with taste.

3) Transparent PNGs are where drop-shadow shines

If your image is a JPEG (no transparency), drop-shadow() and box-shadow can look similar. Transparent PNGs are where the difference screams “I’m the right tool.”

Hover animation: drop-shadow that feels good

A classic UI move: increase the shadow slightly on hover to feel “lifted.” With filters, you can animate the filter property. Keep transitions short and subtle.

.tile img {
  filter: drop-shadow(0px 12px 16px rgba(0, 0, 0, 0.22));
  transition: filter 160ms ease, transform 160ms ease;
}

.tile:hover img,
.tile:focus-within img {
filter: drop-shadow(0px 20px 26px rgba(0, 0, 0, 0.22));
transform: translateY(-4px);
} 
*,
::before,
::after {
  box-sizing: border-box;
}

.wrap {
  min-height: 420px;
  display: grid;
  place-items: center;
  padding: 24px;
  background: #f4f5f7;
  font-family: ui-sans-serif, system-ui, sans-serif;
}

.tile {
  width: min(520px, 92vw);
  background: #ffffff;
  border: 1px solid #e6e6e6;
  border-radius: 18px;
  padding: 18px;
}

.tile h3 {
  margin: 0 0 10px 0;
  font-size: 16px;
}

.tile p {
  margin: 0 0 14px 0;
  font-size: 14px;
  line-height: 1.45;
  opacity: 0.85;
}

.tile img {
  width: 280px;
  height: auto;
  display: block;
  margin: 0 auto;
}

.tile a {
  color: inherit;
  text-decoration: underline;
}
  

Hover (or focus) to lift

Small shadow + tiny translate = “this is clickable” energy.

Hover lift demo image

Keyboard users can tab here too

CSS Drop Shadow wrap-up: what to remember

  • box-shadow shadows the box. drop-shadow() shadows the silhouette.
  • Opacity is usually controlled in the shadow color (RGBA/HSLA), not with opacity.
  • No spread in drop-shadow(), but stacking layers often gets you the look you want.
  • For text, start with text-shadow, then reach for drop-shadow() when it fits the design.

CSS Drop Shadow Conclusion

CSS drop shadows are a versatile tool for adding depth and emphasis to your designs. By understanding the differences between box-shadow, text-shadow, and drop-shadow(), you can create more visually appealing and interactive user interfaces.