The box-shadow
property is obviously useful for light shadows behind elements providing a sense of dimensionality and separation. But box-shadow
had some tricks up its sleeve, particularly with how a box shadow doesn’t need to be soft, can be stacked, and doesn’t even need to be particularly nearby.
We’re going to get to these “boxy buttons,” but we’re ultimately going to use box-shadow
to make them, so let’s take a quick box-shadow
journey.
The basic use cause for box-shadow
is giving an element the appearance of three-dimensionality by applying a shadow underneath it as if it’s been lifted off the surface.
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/Screen-Shot-2017-06-04-at-6.58.34-AM.png?ssl=1)
The slight shadows applied to those white boxes are done by:
.module {
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
}
Which is to say:
- Make an exact copy of the shape this element (respecting the
border-radius
, for instance) and put it underneath the element - Offset it by 0 horizontally and 1px (down) vertically
- Blur it by 3px. There is an optional parameter after the blur called spread which allows you do expand or contract the shadow, which defaults to 0 (doing neither).
- The background of it will be black with 0.2 opacity
That’s so basic though. C’mon. We can get weirder than that. Consider:
- You can get extreme with those offsets.
- You don’t have to blur the shadow at all.
- The colors don’t have to be subtle.
And most importantly:
- You can apply multiple shadows
Here are three differently offset shadows with no blur:
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/multiple-shadows.png?ssl=1)
.module {
width: 100px;
height: 100px;
background: white;
box-shadow:
5px 5px 0 #FF9800,
10px 10px 0 #FFC107,
15px 15px 0 #607D8B;
}
We could push those offsets further, making the “shadows” entirely separated from the element:
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/seperated-shadows.png?ssl=1)
.module {
width: 50px;
height: 50px;
background: white;
box-shadow:
55px 55px 0 #FF9800,
110px 110px 0 #FFC107,
165px 165px 0 #607D8B;
}
So now that we know we have the ability to have unlimited shadows of any size that can be placed anywhere… we can draw pixel art! All with a single element! Here’s a burger, fries, and shake done by Marcus Connor:
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/burger-fries-shake.png?ssl=1)
Steve Jobs as done by Codrin Pavel:
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/steve-jobs-pixel-art.png?ssl=1)
Or how about the Mona Lisa done with about 7,500 shadows, by Jay Salvat:
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/mona-lisa.png?ssl=1)
On a slightly more practical level, you can layer box-shadow
to simulate three-dimensionality and directional shadows. Boxy buttons!
The trick is that we use zero-blur shadows laying them on top of each other. If we do that 1 pixel at a time and alternate sides as we do it, they way the shadows stack on top of each other gives us an opportunity to create a 3D box look. Here are the basics:
.boxy-button {
--bottom-color: #999;
--right-color: #ddd;
box-shadow:
1px 0 0 var(--right-color),
1px 1px 0 var(--bottom-color),
2px 1px 0 var(--right-color),
2px 2px 0 var(--bottom-color),
3px 2px 0 var(--right-color),
3px 3px 0 var(--bottom-color),
4px 3px 0 var(--right-color),
4px 4px 0 var(--bottom-color);
}
Keep going with that, and we can make a very boxy button indeed.
![](https://i1.wp.com/css-tricks.com/wp-content/uploads/2020/03/boxy-button.png?fit=1024%2C536&ssl=1)
Toss some transitions on there and we can even make it feel very pressable:
button {
font-family: Roboto, sans-serif;
padding: 1rem 2rem;
font-size: 2rem;
border: 0;
color: #333;
--top-color: #ccc;
--bottom-color: #999;
--right-color: #ddd;
background: var(--top-color);
transition: box-shadow 0.2s, transform 0.15s;
box-shadow: 1px 0 0 var(--right-color), 1px 1px 0 var(--bottom-color), 2px 1px 0 var(--right-color), 2px 2px 0 var(--bottom-color), 3px 2px 0 var(--right-color), 3px 3px 0 var(--bottom-color), 4px 3px 0 var(--right-color), 4px 4px 0 var(--bottom-color), 5px 4px 0 var(--right-color), 5px 5px 0 var(--bottom-color), 6px 5px 0 var(--right-color), 6px 6px 0 var(--bottom-color), 7px 6px 0 var(--right-color), 7px 7px 0 var(--bottom-color), 8px 7px 0 var(--right-color), 8px 8px 0 var(--bottom-color), -5px 20px 40px -8px #999;
}
button:focus, button:hover {
outline: 0;
box-shadow: 1px 0 0 var(--right-color), 1px 1px 0 var(--bottom-color), 2px 1px 0 var(--right-color), 2px 2px 0 var(--bottom-color), 3px 2px 0 var(--right-color), 3px 3px 0 var(--bottom-color), 4px 3px 0 var(--right-color), 4px 4px 0 var(--bottom-color), -5px 5px 12px -8px #999;
transform: translate(3px, 3px);
}
button:active {
outline: 0;
box-shadow: 1px 0 0 var(--right-color), 1px 1px 0 var(--bottom-color);
transform: translate(5px, 5px);
}
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/08/boxy-push.jpg?resize=1024%2C372&ssl=1)
We could use the one-line-at-a-time shadow technique for the “outer” shadow as well, faking the gradient by reducing the opacity of the shadow a bit each time. That makes more a directional shadow look that can be cool.
Here’s an example where the direction goes the other way (thanks to negative box-shadow offsets) and uses the directional shadows.
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2017/06/3dbutton.png?ssl=1)
That’s an awful lot of code for a fun button, but aren’t buttons worth it? With a good bit less code, we can get another pretty fun offset look, only this time using some inset
box-shadow
trickery and little pseudo-elements to fake the continued border look.
button {
background: none;
border: 5px solid black;
padding: 1.5rem 3rem;
box-shadow: 5px 5px red, 10px 10px black, inset 5px 5px white, inset 10px 10px black;
font-family: -system-ui, sans-serif;
font-weight: bold;
font-size: 2rem;
position: relative;
}
button::before, button::after {
content: "";
position: absolute;
background: black;
}
button::before {
top: 100%;
left: 5px;
height: 10px;
width: 5px;
}
button::after {
left: 100%;
top: 5px;
height: 5px;
width: 10px;
}
![](https://i0.wp.com/css-tricks.com/wp-content/uploads/2021/08/offset-button.png?resize=546%2C224&ssl=1)