Designing Beautiful Shadows in CSS

Designing Beautiful Shadows in CSS

Demo Post

In my humble opinion, the best websites and web applications have a tangible “real” quality to them. There are lots of factors involved to achieve this quality, but shadows are a critical ingredient. When I look around the web, though, it's clear that most shadows aren't as rich as they could be. The web is covered in fuzzy grey boxes that don't really look much like shadows. In this tutorial, we'll learn how to transform typical box-shadows into beautiful, life-like ones:

Intended audience

This tutorial is intended for developers who are comfortable with the basics of CSS. Some knowledge around box-shadow, hsl() colors, and CSS variables is assumed.

Why even use shadows?

We'll get to the fun CSS trickery soon, I promise. But first, I wanna take a step back and talk about why shadows exist in CSS, and how we can use them to maximum effect. Shadows imply elevation, and bigger shadows imply more elevation. If we use shadows strategically, we can create the illusion of depth, as if different elements on the page are floating above the background at different levels.

There's also a tactical benefit here as well. By using different shadows on the header and dialog box, we create the impression that the dialog box is closer to us than the header is. Our attention tends to be drawn to the elements closest to us, and so by elevating the dialog box, we make it more likely that the user focuses on it first. We can use elevation as a tool to direct attention. When I use shadows, I do it with one of these purposes in mind. Either I want to increase the prominence of a specific element, or I want to make my application feel more tactile and life-like.

In order to achieve these goals, though, we need to take a holistic view of the shadows in our application.

Creating a consistent environment

For a long time, I didn't really use shadows correctly 😬. When I wanted an element to have a shadow, I'd add the box-shadow property and tinker with the numbers until I liked the look of the result. Here's the problem: by creating each shadow in isolation like this, you'll wind up with a mess of incongruous shadows. If our goal is to create the illusion of depth, we need each and every shadow to match. Otherwise, it just looks like a bunch of blurry borders In the natural world, shadows are cast from a light source. The direction of the shadows depends on the position of the light: In general, we should decide on a single light source for all elements on the page. It's common for that light source to be above and slightly to the left.

If CSS had a real lighting system, we would specify a position for one or more lights. Sadly, CSS has no such thing. Instead, we shift the shadow around by specifying a horizontal offset and a vertical offset. In the image above, for example, the resulting shadow has a 4px vertical offset and a 2px horizontal offset. Here's the first trick for cohesive shadows: every shadow on the page should share the same ratio. This will make it seem like every element is lit from the same light source.

Kartik Thakur
Author
Kartik Thakur
a front-end developer.

Comments