Intro
A great deal of the charm of CSS level 3 (CSS3) comes from the ability of its various features to cut down on background images and Photoshop muscle flexing, allowing us to programmatically create many of our graphic requirements instead. This brings with it many advantages – time saved, less HTTP requests and file weights, and more flexibility to name just a few.
Of course, this does come with a trade off in that many of these feature don’t work in older versions of IE that we might still be required to support.
In this article I’ll cover the venerable text-shadow property, taking you from basics, through interesting applications, and up to advanced considerations. Let’s go.
Basics
At its inception, text-shadow is a pretty simple property, which can be applied to any element:
.shadow1 {
text-shadow: 3px 3px 1px gray;
}
Any textual content inside the elements your text-shadow property is applied to will have the shadow.
The four values inside the property value are as follows:
- Horizontal offset from the text. Positive numbers move the shadow right, negative ones move it left
- Vertical offset from the text. Positive numbers move the shadow down, negative ones move it up.
- Blur radius of the shadow. Larger values make the shadow look more blurry
- Base color of the shadow. This can be any valid CSS color units, including RGBA/HSLA.
The following images show the difference between a simple shadow with a blur radius of 1px, versus 7px:
You can apply multiple shadows to a single selection of text, by simple writing multiple text-shadow values separated by commas:
.shadow3 {
text-shadow: 1px 1px 1px #666,
3px 3px 8px black;
}
Advanced ideas
You can take the simple syntax presented above and go as wild as you like with it. You might just want a very simple raised or inset effect:
.shadow4 {
text-shadow: 1px 1px 1px red,
2px 2px 1px red;
}
.shadow5 {
text-shadow: -1px -1px 1px #555,
-2px -2px 1px #666;
}
Or something much more interesting like a sophisticated 3D effect:
.shadow6 {
text-shadow: -1px -1px 1px #aaa,
0px 4px 1px rgba(0,0,0,0.5),
4px 4px 5px rgba(0,0,0,0.7),
0px 0px 7px rgba(0,0,0,0.4);
}
Or even the legendary flaming text shadow – essential for any heavy metal web site:
.shadow7 {
text-shadow: 0 0 20px #fefcc9,
10px -10px 30px #feec85,
-20px -20px 40px #ffae34,
20px -30px 35px #ec760c,
-20px -40px 40px #cd4606,
0 -50px 65px #973716,
10px -70px 70px #451b0e;
}
How about a more nifty, accurate inset text effect, created using background-clip: text (which is currently only supported in WebKit/Blink-based browsers, unfortunately.)
.shadow8 {
background-color: #333;
-webkit-background-clip: text;
-moz-background-clip: text;
background-clip: text;
color: transparent;
text-shadow: rgba(255,255,255,0.5) 2px 3px 6px;
}
or an over-the-top, awesomely fun giant 3D lego text?
.shadow9 {
text-shadow: 0 1px #808d93,
-1px 0 #cdd2d5,
-1px 2px #808d93,
-2px 1px #cdd2d5,
-2px 3px #808d93,
-3px 2px #cdd2d5,
-3px 4px #808d93,
-4px 3px #cdd2d5,
-4px 5px #808d93,
-5px 4px #cdd2d5,
-5px 6px #808d93,
-6px 5px #cdd2d5,
-6px 7px #808d93,
-7px 6px #cdd2d5,
-7px 8px #808d93,
-8px 7px #cdd2d5;
}
Bear in mind that text-shadow can even be animated using CSS animations – the following example creates a stack of different colored letter shapes, which shift back and forth in a groovy fashion.
.shadow10 {
color: yellow;
text-shadow: 1px 1px 2px rgba(0,0,0,0.7),
5px 5px 1px orange,
6px 6px 2px rgba(0,0,0,0.7),
10px 10px 1px red,
11px 11px 2px rgba(0,0,0,0.7),
15px 15px 1px purple,
16px 16px 2px rgba(0,0,0,0.7);
-webkit-animation: text-snake 1s infinite alternate;
-moz-animation: text-snake 1s infinite alternate;
-ms-animation: text-snake 1s infinite alternate;
animation: text-snake 1s infinite alternate;
}
/* other prefixed animation blocks ommitted for brevity */
@keyframes text-snake {
from {
text-shadow: 1px 1px 2px rgba(0,0,0,0.7),
5px 5px 1px orange,
6px 6px 2px rgba(0,0,0,0.7),
10px 10px 1px red,
11px 11px 2px rgba(0,0,0,0.7),
15px 15px 1px purple,
16px 16px 2px rgba(0,0,0,0.7);
}
to {
text-shadow: -1px 1px 2px rgba(0,0,0,0.7),
-5px 5px 1px orange,
-6px 6px 2px rgba(0,0,0,0.7),
-10px 10px 1px red,
-11px 11px 2px rgba(0,0,0,0.7),
-15px 15px 1px purple,
-16px 16px 2px rgba(0,0,0,0.7);
}
}
Here’s a demo:
See the Pen qtmjw by SitePoint (@SitePoint) on CodePen.
Cross browser comfort?
text-shadow is supported across all modern browsers, with the rather disappointing exception of IE9. Nonetheless, this is not that serious, as text shadow is nearly always a purely eye candy effect, and you should simply do a bit of testing and make sure that your text is still legible, even if the shadow fails to show. This is why I generally don’t recommend using text-shadows along with transparent text colors, even thought it can lead to some interesting possibilities.
One thing to bear in mind is that calculating a lot of shadows can put a strain on the device’s CPU, so be a bit mindful of this if you are planning on using a lot of text shadowing. You might want to turn shadows off on small screen devices (via a media query), and reconsider your plans to have pages full of moving shadowed text all over your page. Your users and clients will thank you for it!
I’d like to thank subtlepatterns.com for providing the awesome background texture: Notebook.
I’d also like to thank Konstantin Kichinsky and Jeff Starr for some inspiring examples.
Chris Mills is a senior tech writer at Mozilla, where he writes docs and demos about open web apps, Firefox OS, and related subjects. He loves tinkering around with HTML, CSS, JavaScript and other web technologies, and gives occasional tech talks at conferences and universities. He used to work for Opera and W3C, and enjoys playing heavy metal drums and drinking good beer. He lives near Manchester, UK, with his good lady and three beautiful children.