This content originally appeared on DEV Community and was authored by Thea
Ever wanted to add beautiful shadows to your text? CSS offers different methods depending on how complex you want your shadows to be. Let’s explore both simple and advanced techniques!
The Simple Way: text-shadow
(Best for Most Cases)
For basic shadows, use the built-in text-shadow
property:
h1 {
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
}
Why this is awesome:
- Super easy to write
- Works in all modern browsers
- Best performance
- Perfect for standard shadows
- Supports multiple shadows in one rule (e.g., add a glow with
-2px -2px 4px rgba(255,255,255,0.3)
)
When You Need Fancy Shadows: The data-text
Technique
Sometimes you want special effects like:
- Gradient shadows that match gradient text
- Multiple shadow layers for depth
- Advanced visual effects
The Problem With Duplicating Text
When creating complex shadows, you might duplicate text in HTML:
<h1>
I ♥ coding
<span class="shadow">I ♥ coding</span>
</h1>
This works but creates messy code that’s hard to maintain.
A Cleaner Way: Using data-text
Here’s a better way using a custom HTML attribute:
<h1 data-text="I ♥ coding">I ♥ coding</h1>
Then in your CSS:
h1 {
position: relative;
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
color: transparent; /* If -webkit-text-fill-color fails */
}
h1::before {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
z-index: -1;
background: linear-gradient(135deg,
rgba(102, 126, 234, 0.3),
rgba(118, 75, 162, 0.3));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
transform: translate(2px, 3px);
filter: blur(1px);
}
Using attr(data-text)
means you only write the text once in HTML. If you later change the text, you don’t have to edit multiple places.
How It Works
-
data-text
attribute: Stores your text in HTML -
attr(data-text)
: CSS grabs the text from the attribute -
::before
: Creates a shadow layer behind the real text -
transform
: Moves the shadow slightly -
filter: blur()
: Makes the shadow soft
Pro Tip: Use filter: blur()
sparingly. It’s rendered on the GPU but can cause jank on lower-end devices. Avoid animating elements with blur
or backdrop-filter
.
Also, backdrop-filter
has limited support in some older browsers, especially Firefox on Android.
Adding a Second Shadow Layer
For extra depth, add another layer with ::after
:
h1::after {
content: attr(data-text);
position: absolute;
top: 0;
left: 0;
z-index: -2;
background: linear-gradient(135deg,
rgba(102, 126, 234, 0.2),
rgba(118, 75, 162, 0.2));
-webkit-background-clip: text;
background-clip: text;
-webkit-text-fill-color: transparent;
transform: translate(4px, 5px);
filter: blur(2px);
opacity: 0.6;
}
Note: Stacking pseudo-elements like this adds a bit of rendering complexity, so reserve it for cases where text-shadow
isn’t enough.
Important Things to Know
Browser Support
- Works in Chrome, Firefox, Edge, and Safari
-
-webkit-
prefixes (like-webkit-background-clip
) are mainly for older browsers - Always test your designs in different browsers
Performance Tips
- Avoid animating these effects (can slow down your page)
- Too many
filter: blur
effects may lag on low-end devices - For simple shadows,
text-shadow
is always faster
Accessibility
- These effects are visual only and won’t affect screen readers
- Make sure your text has enough contrast with the background
Alternative Methods
Using drop-shadow
Filter
For some effects, you can try:
.filter-shadow {
filter: drop-shadow(2px 2px 4px rgba(0,0,0,0.3));
}
drop-shadow
works better than text-shadow
for see-through text or images, because it keeps the shadow looking clean around transparent parts.
Multiple text-shadow
Layers
For simple gradient-like effects:
.multi-shadow {
text-shadow:
1px 1px 0 rgba(102, 126, 234, 0.4),
2px 2px 0 rgba(118, 75, 162, 0.3);
}
When to Use Each Method
Situation | Best Technique | Why |
---|---|---|
Simple shadows | text-shadow |
Easy to write, best performance |
Multiple solid layers | Multiple text-shadow |
Good balance of simplicity and effect |
Gradient shadows |
data-text method |
Only way to achieve gradient shadows behind gradient text |
Performance critical | text-shadow |
No pseudo-elements or complex rendering |
Complex animations | filter: drop-shadow |
Can be GPU accelerated; works well with transforms |
Accessibility | All methods | Ensure high contrast (4.5:1) |
Try It Yourself
Check out all these shadow techniques with working examples and copy-paste code:
Text shadows can take your design from plain to wow. Start with the simple text-shadow
for most cases, and level up to the data-text
technique when you need those fancy gradient effects.
Happy coding!
This content originally appeared on DEV Community and was authored by Thea