top of page

Designing Beautiful Shadows in CSS

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.

“Do you have a design in mind for your blog? Whether you prefer a trendy postcard look or you’re going for a more editorial style blog - there’s a stunning layout for everyone.”

You’ll be posting loads of engaging content, so be sure to keep your blog organized with Categories that also allow visitors to explore more of what interests them.

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.

I want the applications I build to feel tactile and genuine, as if the browser is a window into a different world. Shadows help sell that illusion.

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.

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 very-far-away light source, like the sun.

Next, let's talk more about elevation. How can we create the illusion that an element is lifting up towards the user?

We'll need to tweak all 4 variables in tandem to create a cohesive experience. The first two numbers—horizontal and vertical offset—scale together in tandem. The vertical offset is always 2x the horizontal one.

Two other things happen as the card rises higher:

  • The blur radius gets larger.

  • The shadow becomes less opaque.

(I'm also increasing the size of the card, for even more realism. In practice, it can be easier to skip this step.)

There are probably complex mathematical reasons for why these things happen, but we can leverage our intuition as humans that exist in a lit world.

If you're in a well-lit room, press your hand against your desk (or any nearby surface) and slowly lift up. Notice how the shadow changes: it moves further away from your hand (larger offset), it becomes fuzzier (larger blur radius), and it starts to fade away (lower opacity). If you're not able to move your hands, you can use reference objects in the room instead. Compare the different shadows around you.

Because we have so much experience existing in environments with shadows, we don't really have to memorize a bunch of new rules. We just need to apply our intuition when it comes to designing shadows. Though this does require a mindset shift; we need to start thinking of our HTML elements as physical objects.

So, to summarize:

  1. Each element on the page should be lit from the same global light source.

  2. The box-shadow property represents the light source's position using horizontal and vertical offsets. To ensure consistency, each shadow should use the same ratio between these two numbers.

  3. As an element gets closer to the user, the offset should increase, the blur radius should increase, and the shadow's opacity should decrease.

  4. You can skip some of these calculations by using our intuition.

7 views0 comments

Recent Posts

See All


bottom of page