Mastering Box Shadows

Share this article

Today we will study the art of mastering shadows with CSS3. There are two types: box-shadow and text-shadow, defined respectively in the modules and CSS3 Text. Both box and text work in a similar manner – the definition of text-shadow is written, pointing to the definition of box-shadow, with some exclusions. Let’s begin with box shadows:

Browser Support

CSS3 box-shadow is supported in IE10 and and other modern browsers. You can also use it in in your metro style apps for Windows 8 built with html/js.

box-shadow

First of all there is one thing you should remember: the shadow does not increase or decrease the size of the box or its border. The spec says: shadows do not trigger scrolling or increase the size of the scrollable area. To create the most basic shadow, all you need is to define the first two parameters of the rule: horizontal and vertical offset of the shadow (1.1):
box-shadow: 3px 3px;
A positive value moves the shadow to the right and down, and a negative one to the left and up. If you don’t specify the shadow’s color, most browsers will use the text color in current context (1.2). (The spec changed in February 2012, in previous edition omitted box-shadow “colors were UA-chosen colors”. So you may find some browsers with a different behavior.):
box-shadow: 3px 3px; color:blue;
To set the color of the shadow, you need to add a color value at the end (1.3):
box-shadow: 3px 3px darkgreen;
To define the color you can use any of the available CSS3 notations: #RGB, #RRGGBB, namely, by rgb() or rgba() and hsla() functions with alpha-channel. The hsla-function is very useful while building complex samples.

Blurring

The third one length you can set is a blur radius — a positive value defining how much the shadow’s edge is blurred (2.1–2.3):
box-shadow:3px 3px 3px darkgrey;
By default, the blur-radius equals zero and the shadow’s edge is sharp. By combining blurring with the shadow’s offsets, you can achieve many effects. On the sample (2.3) both offsets are equal to zero, but thanks to the blurring effect there’s a shadow around the box:
box-shadow:0 0 9px black;
The blurring algorithm is not defined by the spec itself, but it says that the blurring effect should approximate the Gaussian blur with a standard deviation equal to half of the blur radius. In other words it means that the actual shadow generated by different UAs can differ at times. The fourth length is for spread-distance, this expands or contracts the shadow. By default, the shadow’s size equals to the box’s, but by using the spread you can change it. Also, I should note here that this parameter was introduced in later spec versions, so there’s many out of date tutorials on the wild web with no idea on its existence. ;) To expand the shadow, set a positive spread-distance (3.1, 3.2):
box-shadow:6px 6px 0px 4px darkred;
To contract — use a negative one (3.3):
box-shadow:12px 12px 8px -4px darkred;
On the sample above (3.4) the shadow has horizontal and vertical offsets of 6px to the left and down, and is expanded for 8px from each side:
box-shadow:6px 6px 0 8px grey;
If you use rounded corners on your box, expect that the border-radius of the expanded shadow will be also scaled up (3.5):

Inner Shadow

One more interesting modifier you can define is the “inset” keyword, which allows you to draw an inner shadow in your box (4.1-4.4):
box-shadow:inset 4px 4px rgba(66,66,66,0.5); /* (4.1) */
box-shadow:inset 4px 4px 0 8px rgba(198,198,198,1); /* (4.2) */
box-shadow:inset -2px -2px 8px 0px black; /* (4.3) */
box-shadow:inset 0 0 4px 0px black; /* (4.4) */
Note that the inner shadow is drawn only inside the box, and if you use positive spread-distance on inner shadow it means contracting the shadow’s perimeter shape (4.2).

Multiple Shadows

And the last one piece of the mosaic: you can define as much shadows for the same box as you want by writing all of them comma-separated in the same rule. To create a rainbow shadow (5.1) all you need to do is to write up seve shadows with increasing spread-distance:
box-shadow: 0 0 2px 1px red,

           0 0 2px 2px orange,

           0 0 2px 3px yellow,

           0 0 2px 4px green,

           0 0 2px 5px lightblue,

           0 0 2px 6px blue,

           0 0 2px 7px violet;
Note that the shadow effects are applied front-to-back. The violet shadow one will be drawn first, on top of it will be drawn the blue one and so on. The red one will be drawn at the end, on top of other shadows, and finally — the box itself with all its content. As all the shadows are independent, you can easily combine shadows with different offsets (5.2):
box-shadow: -6px -6px 8px -4px rgba(255,0,0,0.75),

           6px -6px 8px -4px rgba(0,255,0,0.75),

           6px 6px 8px -4px rgba(255,255,0,0.75),

           -6px 6px 8px -4px rgba(0,0,255,0.75);
Or combine outer and inner shadows (5.3):
box-shadow: inset 0 0 8px lightgray,

           1px 1px 3px darkgray;
Here is an underline (bottom shadow) sample (5.4):
box-shadow: 0 1px red,

           0 3px 3px -2px black
By adding some special effects on the :before and :after pseudo-classes with content, you can create a slick-box described by Matt Hamm (5.5):
.slick-box {

   position: relative;

   height: 50px;

   border: 1px solid #efefef;

   background: #fff;

   box-shadow: 0 1px 4px rgba(0, 0, 0, 0.27), 0 0 40px rgba(0, 0, 0, 0.06) inset;

}

 

.slick-box:before, .slick-box:after {

   content: '';

   z-index: -1;

   position: absolute;

   left: 10px;

   bottom: 10px;

   width: 70%;

   max-width: 300px; /* avoid rotation causing ugly appearance at large container widths */

   height: 55%;

   box-shadow: 0 8px 16px rgba(0, 0, 0, 0.3);

   transform: skew(-15deg) rotate(-6deg);                

}

           

.slick-box:after {

   left: auto;

   right: 10px;

   transform: skew(15deg) rotate(6deg);                

}
To simplify the code I’ve removed all vendor prefixes, but while trying to reproduce it you should use all of these, -ms-transform, -webkit-transform and so on.

Common syntax

Summing up the common syntax for box-shadow looks like this:
box-shadow:  [ ,  ]*;

 = inset? && [ {2,4} && ? ]
The last one rule in a full version means:
box-shadow: inset? h-offset v-offset blur-radius spread-distance color;
The blur-radius and the spread-distance can be omitted. The inset keyword switched the shadow form outer to inner.

Interactive Sample

If you wish to play with shadows in an interactive way my colleagues created a cool demo for the Build conference in the last September: “Hands-on: box-shadow“.

A Note

The CSS properties discussed in this article are defined in the CSS3 Backgrounds and Borders module, which is currently in the Working Draft status. Meanwhile, it seems to be quite stable though it still can change in details.

Frequently Asked Questions (FAQs) about Mastering Box Shadows

What is the difference between box-shadow and drop-shadow in CSS?

The box-shadow property in CSS is used to apply shadow effects around an element’s frame. You can set multiple effects separated by commas. A box-shadow is described by X and Y offsets relative to the element, blur and spread radius, and color.

On the other hand, the drop-shadow filter function applies a shadow effect to the alpha channel of an element. This means the shadow is applied to the entire element, including any transparent space. Unlike box-shadow, drop-shadow applies to the whole element including any content, border, and padding.

How can I create a blur effect with box-shadow?

The blur effect in box-shadow can be achieved by adjusting the third value in the box-shadow property. This value represents the blur radius. The larger the value, the bigger and lighter the shadow becomes, creating a blur effect. For example, box-shadow: 10px 10px 5px grey; will create a grey shadow that’s offset 10px to the right and 10px down, with a blur radius of 5px.

Can I apply multiple shadows to one element?

Yes, you can apply multiple shadows to one element by comma-separating the values in the box-shadow property. Each value set will create a new shadow, and they will be layered on top of each other with the first shadow on top. For example, box-shadow: 3px 3px 5px black, -1px -1px 5px grey; will create a black shadow offset 3px to the right and down with a blur radius of 5px, and a grey shadow offset 1px to the left and up with the same blur radius.

How can I create a shadow only on one side of the element?

To create a shadow on one side of an element, you can set the horizontal or vertical offset and keep the other offset at zero. For example, box-shadow: 10px 0 5px grey; will create a shadow that’s offset 10px to the right of the element, with no vertical offset.

What does the ‘spread radius’ in box-shadow do?

The spread radius in box-shadow, represented by the fourth value, determines how far the shadow extends from the box. Positive values will cause the shadow to expand and grow bigger, while negative values will cause the shadow to shrink. If not specified, it will be 0 (the shadow will be the same size as the element).

Can I use box-shadow to create a border effect?

Yes, you can use box-shadow to create a border effect. By setting the blur radius to 0 and adjusting the spread radius, you can create a solid, sharp shadow that can mimic a border. For example, box-shadow: 0 0 0 10px black; will create a 10px black border around the element.

How can I make the shadow inside the box instead of outside?

You can create an inner shadow by adding the keyword ‘inset’ before the other box-shadow values. For example, box-shadow: inset 5px 5px 10px black; will create a black shadow inside the box, offset 5px to the right and down, with a blur radius of 10px.

Can I use RGBA color values in box-shadow?

Yes, you can use RGBA color values in box-shadow to control the opacity of the shadow. For example, box-shadow: 10px 10px 5px rgba(0,0,0,0.5); will create a semi-transparent black shadow.

How does box-shadow affect the layout of my page?

The box-shadow property does not affect the layout of your page. The shadow is drawn outside the element’s border and does not take up space, so it does not affect the position or size of surrounding elements.

Can I animate the box-shadow property?

Yes, you can animate the box-shadow property using CSS transitions or animations. You can smoothly change the shadow’s color, offsets, blur radius, and spread radius over a specified duration. For example, you can create a hover effect where the box shadow grows when you hover over the element.

Konstantin KichinskyKonstantin Kichinsky
View Author

Konstantin Kichinsky works at Microsoft Russia as Academic Developer Evangelist with special focus on HTML5 and IE, and apps design and UX for Windows Phone. Catch his blog here.

CSS3HTML5 Dev Center
Share this article
Read Next
Get the freshest news and resources for developers, designers and digital creators in your inbox each week