Beyond Depth: Shadows As A Design Tool
CSS shadows are usually the go-to tool for adding depth and dimension to a flat interface. But the box-shadow, drop-shadow(), and text-shadow properties can do much more than simulate elevation. They can be layered, animated, and manipulated to create hover effects, shape-based silhouettes, and even colorized text — all without a single additional image file.
The Inset Veil Hover Effect
Most developers know inset as an optional value for box-shadow that casts a shadow inside an element's bounds, making it look stamped into the page. But because inset shadows are painted over an element's background, they can also act as a full-coverage "veil" that hides whatever is beneath them.
Start with a simple div:
<div class="item"></div>
Give it dimensions, a background color, and a border radius to make a green circle:
.item {
width: 250px;
height: 250px;
background: green;
border-radius: 50%;
}
Now cover the green with a red inset shadow with no blur radius:
.item {
width: 250px;
height: 250px;
background: green;
border-radius: 50%;
box-shadow: inset 250px 250px 0 red;
}
On hover, remove the red inset shadow to reveal the original green background:
.item:hover {
box-shadow: none;
}
See the Pen [Inward Shadow Pt. 1 [forked]](https://codepen.io/smashingmag/pen/qBLdjKR) by Preethi Sam.
This basic mechanic becomes more interesting when you stack multiple inset shadows and combine them with a transition. Add a span inside the .item element:
<div class="item">
<span>The New York Times</span>
</div>
<!-- more items -->
The initial state is a circle with a background image and a stack of inset shadows:
.item {
width: 300px;
height: 300px;
background-image: url('nytimes.svg');
border-radius: 50%;
box-shadow: inset -300px -300px 0 black,
}
.item {
width: 300px;
height: 300px;
background-image: url('nytimes.svg');
border-radius: 50%;
box-shadow:
inset -300px -300px 0 black,
inset 300px -300px 0 green,
inset -300px 300px 0 blue,
inset 300px 300px 0 yellow,
0 0 20px silver; /* standard outset shadow */
color: white;
}
The trick is to remove all inset shadows on hover and make the text color transparent, which reveals the background image underneath the shadow stack:
.item:hover {
box-shadow:
inset 0 0 0 transparent,
inset 0 0 0 transparent,
inset 0 0 0 transparent,
inset 0 0 0 transparent,
0 0 20px silver; /* retain the outset shadow */
color: transparent;
}
A smooth transition makes the reveal seamless:
.item {
width: 300px;
height: 300px;
background-image: url('nytimes.svg');
border-radius: 50%;
box-shadow:
inset -300px -300px 0 black,
inset 300px -300px 0 green,
inset -300px 300px 0 blue,
inset 300px 300px 0 yellow,
0 0 20px silver; /* standard outset shadow */
color: white;
transition:
box-shadow ease-in-out .6s,
color ease-in-out .5s;
}
.item:hover {
box-shadow:
inset 0 0 0 transparent,
inset 0 0 0 transparent,
inset 0 0 0 transparent,
inset 0 0 0 transparent,
0 0 20px silver; /* keeping the outset shadow */
color: transparent;
}
Note that the outward (non-inset) shadow in the stack is intentionally left intact — only the inset shadows are removed on hover. The final effect is a clean image reveal that works with both background-color and background-image. CSS variables make the effect easy to tweak for different colors and sizes:
See the Pen [Inward Shadow Pt. 2 [forked]](https://codepen.io/smashingmag/pen/abPOwRm) by Preethi Sam.
Shadows Casting Shadows
While stacking multiple box-shadow layers is straightforward, creating a shadow of a shadow requires a different approach. The drop-shadow() filter casts a shadow along the element's actual shape rather than its bounding box. When applied to an element that already has a box-shadow, the drop shadow will also cast a silhouette of that box shadow's visible area.
This combination produces effects that look like intersecting shapes, such as a Venn diagram:
.item {
box-shadow: 0 0 20px black ;
filter: drop-shadow(-30px 0 0 blue);
}
See the Pen [Shadow of a Shadow Pt. 1 [forked]](https://codepen.io/smashingmag/pen/ZEVGymY) by Preethi Sam.
Building on the same .item container, nest a div (for the background effect) and an img (purely decorative):
<div class="item">
<div class="background"></div>
<img src="image.jpeg" />
</div>
<!-- more items -->
Apply a box-shadow to the background child element, then stack three drop-shadow() filters on top of it:
/* third circle in the following demo */
.item > .background {
box-shadow: 0 0 40px rgb(255 0 0 / .5);
filter:
drop-shadow(-20px 0 0 rgb(255 0 0 / .5))
drop-shadow(20px 0 0 rgb(255 0 0 / .5))
drop-shadow(20px 0 0 rgb(255 0 0 / .5));
}
These effects respond to transitions as well, making them suitable for interactive elements:
See the Pen [Shadow of a Shadow Pt. 2 [forked]](https://codepen.io/smashingmag/pen/VwqLWqM) by Preethi Sam.
Text Shadows As Color
The text-shadow property can also serve a less obvious purpose: coloring text. By setting the text color to transparent and relying entirely on the shadow, you can render solid-color icons from emoji — a quick icon system without external assets:
/* second column in the below demo */
p {
color: transparent;
text-shadow: 1px 1px 0 black;
}
See the Pen [Textual Shadow Pt. 2 [forked]](https://codepen.io/smashingmag/pen/yLGNXZB) by Preethi Sam.
This approach works because text-shadow applies to the rendered text glyphs themselves. Alternatives like background-clip: text or drop-shadow() could achieve similar results, but they affect the element's background rather than the text, which limits their use cases.
A potential "gotcha" is that underlines on links are not affected by text-shadow. If your design needs underlined links with this effect, pair it with text-decoration and text-underline-offset:
See the Pen [Text Shadow No Likey Link Underlines [forked]](https://codepen.io/smashingmag/pen/YzdXQBY) by Geoff Graham.
p {
color: transparent;
text-shadow: 1px 1px 0 black;
text-decoration-line: underline;
text-decoration color: black;
text-underline-offset: 3px;
}
See the Pen [Shadow-Only Link With Underline [forked]](https://codepen.io/smashingmag/pen/abPOwMB) by Geoff Graham.
The Takeaway
These three experiments — inset shadow veils, shadow-on-shadow silhouettes, and shadow-colored text — show how CSS shadows remain a flexible, well-supported tool for visual effects far beyond depth. With full browser support and no extra assets, they offer a fertile ground for creative front-end design.



