CSS Tip: Multicolor & Cutout Drop Shadows

Joshua Bemenderfer

Box shadows are boring. You heard me. They can only use one color at a time and are slow to animate or transition. You know what would be neat? Making a drop shadow that would use the colors of the element’s background. So if the top left corner of your element was red, the top left corner of the shadow would be red. If the bottom right corner was blue, the bottom left corner of the shadow would be blue. Wouldn’t that be neat? Too bad there’s no way to do it in CSS… Oh wait, there is. Let’s dive in.

The Method

Really, all we have to do is create a pseudo-element directly behind the parent element and have it inherit relevant properties, such as background and border-radius. Then we add a CSS blur() filter. This creates a second copy of the element’s background and blurs it behind the element. Easy as pie. By inheriting the background and related properties, we don’t have to specify them repeatedly.

Even better, if you want to animate / smoosh / squash the shadow in some way, you have the full power of CSS transforms and opacity available to you on the pseudo-element!

What’s the catch? The shadow won’t display in browsers that don’t support the CSS blur filter.

The Code

/* The element that will have the blurred shadow. */
.fancy-box {
  /* We need to set the position value to something other than `static`
   * so that position: absolute for the pseudo-element will be relative
   * to this element. */
  position: relative;

  /* A nice Alligator.io-themed linear gradient. */
  /* This technique works with any and every background type. */
  background: linear-gradient(to bottom right, rgb(107,183,86), rgb(0,143,104));

  /* Whatever else you want in here. */
}

/* The shadow pseudo-element. */
.fancy-box::before {
  content: ' ';
  /* Position it behind the parent. */
  z-index: -1;
  position: absolute;
  top: 0;
  right: 0;
  bottom: 0;
  left: 0;

  /* Inherit the background and border radius of the parent. */
  background: inherit;
  border-radius: inherit;

  /* Blur it for maximum shadowy-ness. */
  filter: blur(15px);

  /* Hide the shadow until the element is hovered over. */
  opacity: 0;
  transition: opacity 300ms;
}

/* Show the shadow on hover. */
.fancy-box:hover::before {
  opacity: 1;
}

The Result

Note how it even works with transparent images! You can finally make shaped shadows! 🎉

Here's a codepen you can play around with.

So how’s the performance? Well, as long as you don’t frequently change the background or adjust the blur radius, it’s about as fast as could be! Overall the performance characteristics of this technique are comparable to the method we showed you earlier for performant box shadow transitions.

  Tweet It
✖ Clear

🕵 Search Results

🔎 Searching...