Better CSS box shadows

Using shadows is a great way to avoid klunky borders in otherwise light layouts and they've long surpassed being "just for decoration" elements in websites and apps alike. Especially when creating different levels of elevation that make some elements appear closer to the user than others – like a stack of elements – the use of shadows can make a big difference.

  • In general the closer something is to the user, the more attention it will get, just like the closest car in traffic (like buttons)
  • Smaller shadows that are closer to the elemet are great for capturing attention, while more diffuse and wide shadows are better suited to separate an element form its surrounding (like overlays)
  • Inset shadows can help create a feeling of plasticity or let elements appear bend inwards

To make a layout with shadows as consistent as possible, we should make sure to pick an imaginary lighting position and stick to it whenever using shadows. Otherwise we risk inconsistencies that look weird to users. Elements casting shadows in different directions also make it harder for the eye to quickly see a hierarchy when it comes to eleviation (z-index).

While those general guidelines are a solid start, the real magic of box shadows reveals itself when we use multiple shadows on the same element. In CSS a regular box shadow has the following properties:

box-shadow: x-offset y-offset blur-radius spread-radius color;

We can however add more shadows on the same element by comma-separating them:

div {
    box-shadow: 0 4px 6px rgba(0,0,0,0.7),
                0 5px 15px rgba(0,0,0,0.2);

The first shadow in this example is a box-shadow how it is often used, generally darker, close to the element and rather sharp with only a bit of blur – the classic way of using box-shadows. The second shadow however has a bigger blur, a higher vertical offset and is rather subtle, giving the element a lot more depth, making it look closer to how we see shadows on objects in real life. If we wanted to achieve a perceived higher elevation that shadow would have to be more subtle the closer it gets and more intense the further "down" it is supposed to be.

While that's already a great improvement over simple box-shadows, we can go even further and create a fake plasticity by adding another shadow to the element. One brand that has incorporated this kind of plasticity into their overall appearance is Algolia. Here's a typical button, which adds a third (inset) shadow to the element, giving it a little edge on the bottom.


.btn {
    box-shadow: 0px 2px 4px rgb(45 35 66 / 40%), /* diffuse shadow behind the button */
                0px 7px 13px -3px rgb(45 35 66 / 30%), /* shadow offset to the bottom for depth */
                inset 0px -3px 0px #d6d6e7; /* boottom "edge" of the button */

Of course we don't always want to make use of every technique just because we can. When shadows are part of the layout however, it is definitely worth spending a bit of time on nailing those basics to get a clean and consistent look.