Text-shadow
Text shadow allows you to put a shadow of the current text behind it, but on top of the background. It is easy to use as a simple elegant shadowing effect. However, this is perhaps most useful when putting text on a background image that may have too much contrast. The text may not be easily visible against the background. Adding a text-shadow allows you to have an outline around the text so that it blends in with the image, but is more visible.
Text shadow was introduced in CSS 2.0, but no browsers implemented it, so it was removed from CSS 2.1 and will be put into CSS 3. Then some of the browsers started implementing it. As a result, browser support is not as high as you might hope, so it is important not to get carried away. For example, it is tempting to make a white background, white text, and a black text-shadow, creating a halo effect. But in browsers that do not support it, the text will be invisible and useless. The following text has this effect applied to it:
This text is invisible and useless in many browsers.
Browser support
Currently, the text-shadow style is supported by 5 browser families; Opera 9.5+, Chrome/Safari 1.1+, Mozilla/Firefox 3.1+, Konqueror 3.4+ and iCab 3.0.3+. It is also possible to emulate some parts of text-shadow in Internet Explorer. It is also possible to use CSS tricks to emulate simple text-shadows in all current browsers. Note that this is one case where Safari and Chrome have completely unrelated implementations. Chrome and Safari will have differing levels of support, and different levels of support.
This page contains examples of text-shadow. To see those examples, you will need a browser that supports text-shadow. I suggest you use Opera, since it is available for free for the common platforms. It is best not to use or rely on Safari's response, since it is by far the most limited and buggy of all. Versions of Firefox are available that support text-shadow, but these are still very much in development, and should not yet be treated as stable. No public final releases of Mozilla/Firefox support text-shadow yet.
Blur
One of the most impressive features of text shadow is the blur. The shadow can be blurred so that it does not have hard edges, and blends in with the background as the edges of the blur become transparent.
Applying a blurred text shadow is quite CPU intensive, as the browser has to blur text to the given radius. It then has to display that blurred text using alpha transparency layered betwen the normal text and its background. Using a blurred text-shadow for a large amount of text may use a lot of CPU power, and may make the page respond slowly to scrolling or mouse interaction. For this reason, it is important to restrict the use of text-shadow to where is makes sense or is really needed.
The larger the radius, the more processing power is needed. Most browsers have a limit. Safari and Opera cannot blur beyond around 100 pixels. iCab cannot blur beyond around 30 pixels. Konqueror has no limit, but will crash if the blur is around 300 pixels. A blur of 200 pixels is so extreme that it is not visible in Konqueror anyway. Mozilla/Firefox has no limit but will become unresponsive with very large blur values. Note that even though Safari and iCab have a limit, you can set a blur higher than that limit. If you set it higher, they will use as much CPU as you might expect for that larger blur, but the result will be a blur at their respective limits.
Opera, Konqueror and Mozilla/Firefox apply a normal linear blur to the shadow. Safari and iCab use system calls to create the blurred shadow. The result in iCab and Safari 3- looks like an exponential shadow, meaning that it is less blurred near its source. As a result, a 30 pixel blur in iCab and Safari 3- looks a lot smaller than a 30 pixel blur in Opera, Konqueror, Firefox and Safari 4+.
A simple shadow
- Safari cannot apply a shadow without a colour specified.
- Safari 3- always makes the offsets 1px less than they should be, so 2 becomes 1, 1 or 0 or -1 become 0, -2 becomes -1 etc.
- Konqueror cannot display a text-shadow that is offset vertically by more than 100 pixels from the source text.
- Mozilla/Firefox displays unnecessary scrollbars if the shadow extends more than half way across the browser window in either direction.
- Mozilla/Firefox 3.1 beta 2- blurs shadows slightly more than the requested blur value, then clips the shadows to the required distance, making them end too abruptly and appear too faint.
- Opera does not show any changes when a shadow is changed with script, until something else causes it to redraw.
In its simplest form, a shadow is created like this:
p { text-shadow: green 3px 2px; }
That would create a green drop-shadow behind the text, positioned two pixels lower than the main text, three pixels to the right of it, and with no blur.
This paragraph has that style rule applied to it.
The following example would create a blue drop-shadow, two pixels higher than the main text, one pixel to the left of it, and with a 0.5em blur:
p { text-shadow: blue -1px -2px 0.5em; }
This paragraph has that style rule applied to it.
The colour can be put first or last in the property value, or omitted completely. If omitted, the CSS 2.0 specification says the text's colour should be used as the colour of the shadow, and CSS 3 say that the browser should assume a default value (typically black). Which one the browser uses will depend on which specification its support is based on. It is best not to rely on either behaviour; always specify an appropriate colour.
If a shadow is applied to one element, and that element has another element within it, the inner element should inherit the shadow from its parent. (Note that this is not specified in CSS 2.0, but has been corrected in CSS 3.) If the inner element also has a shadow of its own, then that shadow will be used instead of the parent's shadow, not in addition to it.
Multiple shadows
- Safari 3- cannot do multiple shadows for one piece of text.
The text-shadow style can accept multiple values, in a comma separated list. According to CSS 2, the shadows are laid down in the order they appear, so if they overlap, the last one that is specified should appear on top. CSS 3 has now changed that so they are applied in reverse order. The response of an individual browser will depend on which specification its implementation is based on. In the following example, the text has both of the shadows from the example above:
p { text-shadow: blue -1px -2px 0.5em, green 3px 2px; }
Safari 3- does not understand this, but it does not apply the normal error handling either (which would be to ignore the whole rule, and allow us to specify two rules, one for Safari 3-, and one for better browsers). It will take just the first shadow from the value, and apply that, ignoring any other shadows. Better browsers will apply all of the shadows together:
This paragraph has that style rule applied to it.
These browsers still have internal limitations to how many shadows they can have for a single piece of text. Opera is limited to 32 tokens in the text-shadow style's value (a token is anything like "1px", "red", or ","), giving a maximum of 11 shadows if the colour and blur are not specified, and 6 if they are. iCab is limited to 129 tokens in the text-shadow style's value, giving a maximum of 43 shadows if the colour and blur are not specified, and 25 if they are. Konqueror has no limit but will crash if you use more than 419 shadows on a single piece of text. Mozilla/Firefox has no limit but can crash if you use a very large number of shadows on a single piece of text (the exact number depends on various factors, but is typically in the order of several thousand shadows).
Shadows overlay previous text
If, for example, you apply a shadow to some text, and offset that shadow so it intersects text from an earlier paragraph, the shadow will appear on top of the text from that earlier paragraph. In Konqueror, Safari, Mozilla/Firefox and Opera, the same thing will happen if you offset the shadow so that it intersects an earlier line of text in the same paragraph. In Opera, the same will happen if it intersects an earlier word in the same line of text.
In most cases, this is not a problem, since most shadows are offset to the right and below, not above or to the left. Even when they are, the blur usually allows the main text to show through the shadow very easily. However, you may need to be careful to avoid obscuring earlier text with a shadow.
Emulating text-shadow in Internet Explorer
Though it pains me to do it, I know many of you will not be interested in using CSS unless it works in Internet Explorer. I will re-emphasize that you should only use text-shadow for decoration, and you should never make your page rely on it. As such, you should be able to make your pages look extra nice in good browsers, while still being OK for Internet Explorer. However, if you still feel the need to make it work in Internet Explorer, there are two proprietary CSS filters that IE can use (the trick relies on filters which did not work in IE 8 betas 1 and 2 since the hasLayout bug was fixed). They are both very limited compared with the proper text-shadow style, but then, this is IE, and that is nothing new.
The two filters are "glow" and "dropshadow". Glow emulates a blurred text-shadow, but cannot be offset. Dropshadow emulates an offset shadow, but cannot be blurred, and cannot be applied to elements with their own backgrounds. So both have very significant problems.
On top of that, both can only be applied to an element if it also has one of the following styles set: display:block+height, display:block+width, or position:absolute. This limits their use even more. Both are also applied to all parts of the element, not just its text. So if you want to use this effect in IE, it is best to wrap the text inside an otherwise unstyled element (such as a span), set one of those styles on it, then apply one of the filters, depending on which effect you want. In general, the glow effect is the one you would want to use.
filter: glow(color=#ffff00,strength=3);
filter: dropshadow(color=#ffff00,offX=5,offY=5);
In both cases, the effect will only be applied over the element itself. If the shadow or glow is large enough to exceed the bounds of the element, it will be truncated.
Because these filters are not valid CSS, and because the other styles required by IE may cause unwanted effects in other browsers, it is best to isolate the IE-specific garbage inside conditional comments to protect good browsers from it:
<style type="text/css">
p.shadowed {
text-shadow: #0000ff 0px 0px 3px;
}
</style>
<!--[if IE]><style type="text/css">
p.shadowed span {
display: block;
width: 100%;
filter: glow(color=#0000ff,strength=3);
}
</style><![endif]-->
...
<p class="shadowed"><span>Text that should have a shadow</span></p>
This text should have a shadow.
Emulating text-shadows by repeating text
The major advantage of using the text-shadow style is that the text only appears once in the source of the page. That means that it looks correct to search engines, it makes sense to screen readers, speech readers, Braille readouts, and text browsers. It is isolated to being just a visual effect. However, if we ignore those browsers and search engines (which I do not like doing, but here we are anyway), then it is possible to emulate basic text shadows by duplicating and carefully positioning text.
The idea is to have an outer container with the text inside it. Also inside it should be other elements that are positioned relating to the container so they are jut a few pixels offset from it in the chosen directions. To do this, the container needs to be a block level element (such as a paragraph or more ususally, a heading), and its contents should be inline elements (such as spans) that contain the repeated text. The container itself must also contain the text directly, as that is needed to stretch it to the correct size.
The inner elements are then absolutely positioned, and set to the same size as their parent container. The last one of these (which will be stacked on top of the others by its implied z-index) will serve as the "original" text. Any others, as well as the base text, will serve as shadows. This means that the offsets must not be too much, or the positioning will look odd. Typically, this effect would be used with two shadows set at -2px,-2px and 2px,2px offset from the "original", to give it a glowing effect:
<style type="text/css">
h2 {
position: relative;
color: #ff0;
}
h2 span {
position: absolute;
top: 4px;
left: 4px;
width: 100%;
height: 100%;
}
h2 span.last {
top: 2px;
left: 2px;
color: #000;
}
</style>
...
<h2>Heading text <span>Heading text</span> <span class="last">Heading text</span></h2>
This paragraph has those styles applied to it. This paragraph has those styles applied to it. This paragraph has those styles applied to it.
Note that you could also use CSS generated content to do this, but that would lose support for IE 7- and Mozilla/Firefox 3.0-, and you would be back where you started.