How To Add Realism With CSS Box Shadow And Text Shadow

You can add visual interest and a sense of realism to a design is by adding depth and one of the popular ways you can add depth is by incorporating the impression of a light source through shadows.

Last week I said I was late to the party in adopting css gradients. Well I’m late to the party in support of css shadows too. And just like last week I want to remind myself how to work with box-shadow and text-shadow and remind myself to use them more often where appropriate.

Browser support for both shadows is very good. As usual the biggest stumbling block will be IE. The good news is box-shadow works in IE9 (though not below). The bad news is text-shadow is IE10 only. Opera-mini is another browser where shadows won’t work. Otherwise it’s pretty much a go.

As with gradients, shadows shouldn’t be design critical. Once again we’re talking progressive enhancement and not absolute requirement. However, unlike gradients, there’se a got’cha with text-shadow which I’ll get to in a bit.

The best part with both types of shadow is they’re incredibly quick and easy to learn and you don’t need to worry about vendor prefixes. As you might expect I created a simple demo to illustrate both box-shadow and text-shadow.

box shadows


The box-shadow property is a way to add one or more drop shadows to the box around an element. Yes, you can add multiple shadows to a single box. These shadows don’t affect the size of the box itself, so no need to adjust widths and heights after adding one and they won’t trigger scrolling.

To set a box shadow you set an optional keyword, then some length values, and finally a color. The css takes the form:

[code type=css]
box-shadow: none | [ , ]*;


[code type=css]
= inset? && [ {2,4} & ? ]
shadow = inset? h-offset v-offset blur-radius spread-distance color;

Let’s look at each of the values and then some real code.

You can have either an outer shadow or an inner shadow.

outer box-shadow — is the default and it paints the shadow outside the border of the box. Inside the border the shadow is clipped.

inner box-shadow — is set with the keyword inset and paints its shadow inside the border, clipping it outside the padding of the element.

There are 4 potential length values you can set, which are in order:

  • horizontal offset — A positive value draws the shadow to the right and negative draws it to the left.
  • vertical offset — A positive value draws the shadow to the bottom and negative draws it to the top.
  • blur radius — Negative values are not allowed. A 0 value means the shadow has a sharp edge. The greater the value, the more blurry the shadow.
  • spread distance — A positive value causes the shadow to expand. A negative value causes it to contract

You can set any color you’d like and you can set it any way you’d like, including hex, rob, rgba, hsl, hsla. Adding a box-shadow is really that easy. The hardest part is probably remembering which comes first, blur or spread.

Here’s some real code from the demo:

[code type=css]
.box {
box-shadow: 6px 7px 10px 3px #3C3013,
inset 2px 2px 2px 1px #4C4023,
inset -2px -2px 2px 1px #8C8083;

The above adds one outer shadow and two inner shadows to the box. I added the two inner shadows so half the border appears to cast a shadow, while the other half casts some reflected light.

Letterpress on business cards and postcards


The text-shadow property is going to be even easier to explain, since it works almost exactly the same way as box-shadow. The main differences are that text-shadow doesn’t have an inset option and there’s no spread value. You can however create multiple text-shadows. The css should look familiar.

[code type=css]
text-shadow: none | [ {2,3} & ? ]#


[code type=css]
shadow = h-offset v-offset blur-radius color;

Text-shadows appear behind the text itself and they’re applied front to back. The first text-shadow defined sits on top of the second, which sits on top of the third. All sit behind the text. The shadow is painted at a stack level between the element’s border and/or background and the element’s text and text decoration.

As with box-shadows, text-shadows don’t influence the layout of the text or trigger scrolling. They aren’t clipped at the shadow’s edge though, and they can show through partially transparent text.

Some real code from the demo:

[code type=css]
h1 {
text-shadow: 1px 2px 3px #fCf0c3,
-1px -1px 1px #2C2003;

Here there are just two shadows and like the box-shadow example above, one is to show the cast shadow, while the other a bit of reflected light. The idea is to create a letterpress effect, which you can see in the demo.

Make mistakes


With gradients it’s not a big deal if the gradient doesn’t render. The aesthetics change, but the functionality shouldn’t. Similar for box-shadows. With text-shadows, it’s a little different since we’re dealing with text.

There’s really one thing to look out for here and that’s in the case your text-shadow doesn’t render (I’m looking at you IE9 and below) you need to ensure the text is still readable and legible. Actually you need to check even if the shadow does appear (you’re off the hook this time IE).

Contrast between text and background is important for legible text. Because we’re adding a shadow to the main text, it could mess up that contrast. You can use your eye most of the time, but keep in mind that things could look different if the shadow isn’t present.

Consider the following:

[code type=css]
body { background: #fff; }

h1 {
color: #fff;
text-shadow: 1px 1px 1px #000;

It’s white text on a white background, but you can read it because of the presence of the shadow. Remove the shadow though…

You get the idea. Just remember to check how your text looks against its background if the shadow itself isn’t present and you should be fine.

There are also a some ways to get text-shadow or an equivalent working in older versions of IE.


The demo

This is easily one of the simpler demos I’ve created and yet the effect is pretty nice and looks like some work went into it. The whole thing was maybe a few minutes to set up and then a few more minutes to play around until I had something I liked.

[code type=html]



The html is just a div with a class of box. There’s an h1 inside. Pretty simple. There’s a little more to the css, though it’s also simple.

[code type=css]
.box {
max-width: 30em;
margin: 2em auto;
height: 15em;
line-height: 15em;
text-align: center;

border: 1em solid #5C4033;
border-radius: 0.25em;

background: #ececec;
background-image: -webkit-linear-gradient(-30deg, #c9c8c3, #cbcac5);
background-image: -moz-linear-gradient(-30deg, #e9e8e3, #ebeae5);
background-image: -ms-linear-gradient(-30deg, #e9e8e3, #ebeae5);
background-image: -o-linear-gradient(-30deg, #e9e8e3, #ebeae5);
background-image: linear-gradient(-30deg, #e9e8e3, #ebeae5);

box-shadow: 6px 7px 10px 4px #3C3013,
inset 2px 2px 2px 1px #4C4023,
inset -2px -2px 2px 1px #8C8083;

h1 {
font-size: 3em;
margin: 0;
color: #4C4023;

text-shadow: 1px 2px 3px #fCf0c3,
-1px -1px 1px #2C2003;

Much of the code above is basic styling on the .box, and the h1. I added a relatively thick border to create the appearance of a picture frame and rounded its corners mostly so you could see how the shadows wrap with the corners. I added a subtle gradient to the background of the box, just because I’m adding them to lots of things after last week’s post.

The main things to note are the box-shadow on .box and the text-shadow on h1.

The box gets 3 shadows.

  • outer cast to the right and bottom that’s a little darker than the border color
  • inner also cast to the right and bottom that’s again a little darker than the border
  • inner cast up and the the left that’s lighter than the border

The text gets 2 shadows that work similar to the latter 2 box shadows. One to cast a darker shadow and one to cast a lighter shadow. Assuming I did everything correct the whole thing should give the appearance of a light source sitting up and to the left of the box.

A spring and its shadow


Yes, I’m late to the shadow party. I swear I have an excuse. My dog ate my text editor or something like that.

Better late than never though, and if you’ve been ignoring box-shadow and text-shadow like me, consider this post a reminder of how easy they are to use and that you can create some interesting effects with very little work.

Remember to check that your text is still legible if the shadow isn’t present or use one of the solutions to produce shadows in older versions of IE.

Otherwise play around and experiment to see what you can do and check out my demo if you need a little help getting started.

« »

Download a free sample from my book, Design Fundamentals.


Leave a Reply

Your email address will not be published. Required fields are marked *