Today
we will start studying the art of mastering shadows with the new CSS3 modules. There
are two types: box-shadow and text-shadow, defined respectively in the
modules CSS3
Backgrounds and Borders and CSS3
Text.
Both
box and text work in a similar manner -
actually the difinition of text-shadow is written pointing to the definition of
box-shadow with some exclusions. In this series, let me
begin with box shadows:
Browser
support
CSS3
box-shadow is supported in IE10 and
9 (with hardware
acceleration) 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.
Offset
and color
To
create the most basic shadow all that 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.
By
default if you didn’t specify the shadow’s color most of the popular browsers
will use the text color in current context (1.2). (The spec changed in February’12,
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 all that you need is just to add a color value at
the end (1.3):
box-shadow: 3px 3px darkgreen;
To
define the color you can use any of available in CSS3 notations: #RGB, #RRGGBB,
namely, by rgb() or rgba() and hsla() functions with alpha-channel.
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 archive various effects.
On the sample (2.3) both offsets are equal to zero, but thanks to the blurring
effect there is 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 some pixels.
Spreading
The fourth
length is for spread-distance to expand or contract the shadow. By default the
shadow’s size equals to the box’s one, but using the spread you can change it.
Also I should note here that this parameter was introduced in later spec
versions, so many out of date tutorials and samples you will find in the wild
web have no idea on its existence.
" src="http://www.codeproject.com/script/Forums/Images/smiley_wink.gif" />
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;
Defining
spread value you can think on it as a shadow scaling operation, but actual
algorithm if defined by the spec in a little bit more complex way using
blurring analogy and deleting transparent or opaque pixels.
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
Finally
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);
box-shadow:inset 4px 4px 0 8px rgba(198,198,198,1);
box-shadow:inset -2px -2px 8px 0px black;
box-shadow:inset 0 0 4px 0px black;
Note
that the inner shadow is drawn only inside the box. And if you use positive
(expanding) 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.
For
example to create a rainbow shadow (5.1) all you need to do is to write up 7
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 (or a 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;
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 removed all the vendor prefixes, but while trying to
reproduce it you should use all these -ms-transform, -webkit-transform and so
on.)
Common
syntax
Summing
up the common syntax for box-shadow looks like this:
box-shadow:
<shadow> [ , <shadow> ]*;
<shadow>
= inset? && [ <length>{2,4} && <color>? ]
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
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 it still can change in details.