More realistic drop shadows with CSS

February 8, 2013

When using the traditional box-shadow CSS attribute, the result is often quite flat, making it look anything but realistic. In a recent project I had a design where the elements where dropping slightly tilted shadows. The normal approach would be to either to export the shadow as an image and position it under the element or then just use box-shadow, which would look like the item is lying flat on the ground. I opted instead to experiment a bit. And this is what I came up with.

/* Drop shadow normal */
.dropshadow:after{
	content: '';
	position:absolute;
	z-index:-1;
	bottom:-3px;
	width:94%;
	left:50%;
	margin-left:-47%;
	height:30px;
	box-shadow: 0 16px 30px -5px rgba(0, 0, 0, 1);
	-webkit-transform: perspective(800px) rotateY(0deg) rotateX(45deg);
	-moz-transform: perspective(800px) rotateY(0deg) rotateX(45deg);
	-ms-transform: perspective(800px) rotateY(0deg) rotateX(45deg);
	-o-transform: perspective(800px) rotateY(0deg) rotateX(45deg);
	transform: perspective(800px) rotateY(0deg) rotateX(45deg);
}
/* Drop shadow: tilt, right*/
.dropshadow.tr:after{
    content: '';
	bottom:0px;
	width:100%;
	left:50%;
	margin-left:-62%;
	-webkit-transform: perspective(300px) rotateY(-40deg) rotateX(50deg);
	-moz-transform: perspective(300px) rotateY(-40deg) rotateX(50deg);
	transform: perspective(300px) rotateY(-40deg) rotateX(50deg);
}
/* Drop shadow: tilt, left*/
.dropshadow.tl:after{
	content: '';
	bottom:0px;
	width:100%;
	left:50%;
	margin-left:-40%;
	-webkit-transform: perspective(300px) rotateY(40deg) rotateX(50deg);
	-moz-transform: perspective(300px) rotateY(40deg) rotateX(50deg);
	transform: perspective(300px) rotateY(40deg) rotateX(50deg);
}

Here’s a live preview, the upper row is the one which has these classes applied, the lower row only has the default box-shadow style. If you hover over an element it will become transparent and you’ll see how the effect is created.

The code is pretty self-explanatory, but I’ll try to explain it briefly.
By using the :after selector we’re able to add an element which is absolute positioned under the main element, we then rotate the new element on it’s y and x axis to change the box-shadow that it creates. Because the after-element is positioned under the main element the user should never be able to see what actually creates the shadow, giving the illusion that the main element is dropping the shadow.

Tags