We often think of shadows in CSS as something to reach for when we want to add depth to a design. The impression of a shadow adds elevation to an element, giving the page another dimension. But shadows can be used for more than depth. Let’s experiment with different shadows — two CSS properties and a filter — to make interesting hover effects, different text styles, and even casting shadows on other shadows.
The world of post-modern web design is one where the light doesn’t cast many shadows. That doesn’t mean CSS shadows are going away. On the contrary, they’ve become more adaptive. Shadows are an incredibly useful design element. We know they add depth to an otherwise two-dimensional web design, but did you know we can stack, animate, and manipulate them in ways that go beyond that?
I’ve been experimenting with shadows. In this article, I’m going to share several “tricks” I’ve discovered along the way and how they can be used to create interesting effects that have little to do with their primary role of adding depth. We’ll look at an effect that works by stacking layers of shadows that transition on hover. After that, I will show you how to make a shadow of a shadow. Lastly, we’ll play with shadows on text as an alternative to color.
Ready for some fun? Let’s start with an interesting hover effect.
The Introspective Shadow Hover Effect #
Most of us are familiar with the inset
keyword. It’s an optional value of the CSS box-shadow
property.
When inset
is specified, the shadow is cast inside the element, directed inward.
It’s commonly used to make it look as if an element has been stamped
into the surface of the web page. We are going to push that shadow
further, both metaphorically and literally, to create an overlay hover
effect for image transitions.
Just as we can control the shadow’s blur radius — how far the shadow spreads outward — we can choose to apply no blur at all to the shadow. We can combine that with the fact that inset shadows are painted over an element’s background (unlike default shadows that are cast beneath the element) to create what I call a “veil” that sits on top of an element.
Let’s start with a single div
in the HTML:
There’s nothing to see yet. So, let’s add some dimensions, a background color, and a border radius to make a green circle.
This is nothing fancy so far. I merely want to demonstrate that we can essentially cover the green background with a red inset box-shadow
:
Now we have a red circle with a green background beneath it. We can remove the red inset shadow on hover to reveal the green background:
Since
shadows can be layered and are supported by CSS transitions, let’s
incorporate that for a more fluid design. First, I’m going to update the
HTML a bit by adding a span
inside the .item
:
For the CSS, it’s the same idea as before. We want a circle with an inset shadow and a background:
The difference so far is that I am using a background-image
instead of a background-color
. They are absolutely interchangeable for the hover effect we’re working on.
Next, I’m going to do two things. First, I’m going to stack more inset shadows inside the .item
. Then I’m changing the text color to white, but only for a moment so the background image shows all the way through.
Even
after we add those four extra shadows, we still are left with only a
black circle that says “The New York Times” on it in white. The trick is
to remove those shadows on hover, change the color of the text to transparent
, and reveal the logo beneath our stack of inset shadows.
That works! But perhaps we should add a little transition in there to smooth it out:
The only other thing I think that’s worth calling out is that the outward shadow in the stack is not removed when the .item
is hovered. I only want to remove the inset shadows.
Here’s the final result:
I used CSS variables throughout so you can change the colors of the shadows and the size of the element.
Casting A Shadow Of A Shadow #
If we learned anything from that last example, it’s that shadows are visually interesting: they can bend, fade, intersect, and transition. But what about a shadow casting another shadow? Can we create a shadow of an element’s shadow?
This is not the same as stacking layers of shadows as we did earlier. Rather, we will be making a silhouette of a shadow. And because we have a second way to add shadows to elements with the CSS drop-shadow()
filter, we can do exactly that.
A drop-shadow()
is a little different than a box-shadow
. Where a box-shadow
casts a shadow along the physical edges of the element’s bounding box, a drop-shadow()
ignores the box and casts a shadow along the element’s shape.
When drop-shadow()
is given to an element with a box-shadow
, the shadow from the box-shadow
will cast a shadow of its own. We can combine these to make interesting effects, like a Venn diagram shape.
This
simple combination of box and drop shadows can lead to interesting
designs, like shadows that cast shadows. Let’s start with some HTML that
includes the same .item
element we used in the last section. This time, we’ll place two child elements inside it, another div
and an img
:
The .item
is merely serving as a container this time. The real work happens on the .background
child element. The image is purely there for decoration. We’re going to set a box-shadow
on the .background
element, then add a stack of three drop-shadow()
layers to it:
We can also use transitions with these effects (as in the middle circle below).
The Textual Shadow #
The last effect we’re going to look at involves the CSS text-shadow
property. It’s actually less of a complicated “trick” than it is a
demonstration of using and showing just the shadow of a text element for
color purposes.
Specifically, I’m talking about transparent text with a shadow on it:
Notice the emoji? Instead of the full-color deal, we normally get, this emoji is more like an icon filled with a solid color. This is one way to make a quick and dirty icon system without drawing them or working with files.
We could have also pulled this off with background-clip: text
to clip around the shape of the emoji or apply a drop-shadow()
. However, that affects the background, limiting where it can be used. Plus, I like the idea of using text-shadow
with text elements since that’s what it’s used for, and emoji are part of the text.
You might think there’s a “gotcha” with underlines. For example, text-shadow
ignores the text decoration of links.
No big deal. If you need to support underlines, we can reach for the CSS text-decoration
and text-underline-offset
properties:
Conclusion #
That’s
a look at three interesting ways to use CSS shadows as more than that
thing you use to add depth. We looked at one way that uses inset shadows
to hide the contents of an element’s background for a neat hover
effect. Then there was the idea of combining box-shadow
and drop-shadow()
to cast a shadow of another shadow. We capped things off with a quick way to manipulate text and emoji with text-shadow
.
I hope these experiments give you the inspiration to do some CSS shadow experiments of your own. Shadows and gradients are perhaps the two most important CSS features for “drawing” with CSS, like many of the examples you’ll see on Lynn Fisher’s A Single Div project. Shadows have incredible browser support, so the options are plentiful as far as what we can do with them.
Further Reading On SmashingMag #
- “Lesser-Known And Underused CSS Features In 2022,” Adrian Bece
- “Fluid Sizing Instead Of Multiple Media Queries?,” Ruslan Yevych
- “CSS Generators,” Iris Lješnjanin
- “Creating A High-Contrast Design System With CSS Custom Properties,” Brecht De Ruyte
No comments:
Post a Comment