CSS & Web Design

CSS Box Shadow Guide: Building Layered, Realistic Shadows

By Smart Tools Utility Team · Published October 7, 2026 · Updated October 7, 2026 · 8 min read

A shadow is one of the cheapest ways to tell a visitor which part of a page is raised, clickable or in front. It is also easy to get wrong: a single heavy, dark blur looks like a smudge, while a few soft layers look like real light. The CSS Box Shadow Generator builds stacked shadows with sliders and produces ready-to-paste CSS. This guide explains every value, shows what stacking does, covers the edge cases (inset, negative spread, shapes that are not rectangles) and ends with how to animate shadows sensibly. All pixel results quoted below were measured in a Chromium browser.

The anatomy of a box-shadow

The tool's default layer produces this line:

box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.25);

Read left to right: horizontal offset, vertical offset, blur radius, spread radius, colour. Positive horizontal values push the shadow right, positive vertical values push it down. Blur softens the edge: 0 gives a hard copy of the box, larger numbers spread the edge over a wider band. Spread grows or shrinks the shadow before it is blurred. An optional inset keyword at the start moves the shadow inside the box.

In the tool each layer has six controls and an inset switch:

The preview is a 160 by 160 pixel white box with 12px rounded corners. Those, and the Light or Dark Preview background, are only for display. The copied CSS contains the box-shadow line and nothing else, so the shadow will follow your element's own size and border-radius.

Using the generator

  1. Adjust the first layer's sliders and watch the preview box.
  2. Click Add Layer to stack another shadow. New layers start at 0px, 8px, 16px blur, 0 spread, black at 15% opacity.
  3. Use the trash button to remove a layer. It is hidden when only one layer is left. Layer titles are not renumbered: remove Layer 1 and add another, and the list reads Layer 2, Layer 3.
  4. Flip Inset on a layer for an inner shadow.
  5. Check the shape on both Light and Dark preview backgrounds.
  6. Click Copy CSS and paste the declaration into your rule.
The Box Shadow Generator with three shadow layers of increasing offset and blur, a white card with a soft shadow in the preview, and three-line CSS output
Three layers at 1px, 4px and 16px vertical offset with 2px, 8px and 32px blur, each at 12% black.

Why layers look more realistic

Real shadows are not uniform. Close to an object, the shadow is small and dark (the contact shadow); farther out, it becomes wide and faint (the ambient shadow). One CSS shadow has one blur radius, so it can only approximate that. Stacking several shadows with doubling offsets and blurs gets closer. The recipe in the screenshot above is:

box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.12),
            0px 4px 8px 0px rgba(0, 0, 0, 0.12),
            0px 16px 32px 0px rgba(0, 0, 0, 0.12);

The comparison below puts that next to two single-layer shadows. The wide single shadow looks like a dark halo; the narrow one only works for a small lift; the three-layer version has a tight edge and a soft fall-off at once. Because each layer uses a low opacity, the combined darkness stays modest.

Three white cards on a pale grey background, two with a single shadow and one with three stacked shadows
Comparison rendered from CSS produced with the tool: a wide single shadow, the tool's default single shadow, and the three-layer shadow.

A few rules of thumb that hold up well:

Ready to design a shadow?

Open the Box Shadow Generator

Stacking order and layer interaction

In CSS, the first shadow in the list is painted on top. We checked it by giving a box two shadows with the same extent, 0 0 0 20px red, 0 0 0 20px blue: the ring was red. In the tool, Layer 1 is the first line of the output, so it sits on top of the later layers. This matters when layers overlap at different opacities or use different colours, for example a coloured glow behind a dark contact shadow.

Spread and inset in practice

Negative spread shrinks the shadow, which lets you keep a shadow only on one side. We rendered a 100 by 100 box with box-shadow: 0 25px 0 -15px #000. A strip of shadow showed under the box (the pixel 5px below its bottom edge was black), while the pixel just outside its left edge and the pixel beside its right edge stayed white. It is how "lifted from the bottom" and "floor reflection" shadows are made. In the tool, make the Y Offset larger than the size of the negative Spread (here 25 against 15), so part of the shadow pokes out below the box.

Inset draws the shadow inside the padding edge. In our test, inset 0 10px 0 0 #000 coloured the top 10px inside the box and left the middle white. Use it for pressed buttons and recessed fields. Mixing inset and outer layers on one element is how soft "pill" and neumorphic looks are produced; our Neumorphism Generator focuses on that style.

One more property of box shadows: they are drawn only outside the element's border box (or inside, for inset). The shadow is not drawn underneath the element itself. If the element's background is transparent or semi-transparent, you see the page behind it there, not the shadow, and in our triangle test below the shadow was likewise absent inside the box.

Shadows follow the box, not the artwork

A box-shadow follows the element's rectangular box, with rounded corners if border-radius is set. It does not follow an image's transparent edges or a shape made with the border trick. We tested a CSS triangle: with box-shadow: 10px 10px 0 0 #000 the pixel at the right of the triangle's bounding box was black (a rectangular shadow), whereas with filter: drop-shadow(10px 10px 0 #000) the same pixel stayed white and the shadow followed the triangle's slanted edge. If you need a shadow around a transparent PNG, an icon or an irregular clip, use filter: drop-shadow(). It takes a single shadow without spread or inset. For text, use text-shadow.

Animating shadows on hover

A shadow that grows on hover makes cards feel interactive. You can transition box-shadow directly:

.card {
  box-shadow: 0px 1px 2px 0px rgba(0, 0, 0, 0.2);
  transition: box-shadow 0.2s ease;
}
.card:hover {
  box-shadow: 0px 10px 20px 0px rgba(0, 0, 0, 0.4);
}

We sampled a 0.5s version of this halfway through and read rgba(0, 0, 0, 0.32) 0px 6.39978px 12.7996px 0px, a value between the two states, so every number is interpolated. Two details help. First, the number of layers does not have to match: when we went from one layer to two, the first layer held steady and the second grew in from nothing. Still, for the cleanest result, keep the same layer count in both states. Second, a shadow change makes the browser repaint the element, which is fine for a few cards but can get heavy on large or numerous elements. A common technique is to put the larger shadow on a pseudo-element and transition only its opacity. Respect visitors who prefer reduced motion by shortening or removing the transition inside @media (prefers-reduced-motion: reduce).

Dark backgrounds, accessibility and limits

A shadow darkens whatever is behind it, so black shadows on dark pages are barely visible: 25% black over the dark slate preview colour (#1e293b) only moves it to roughly rgb(22, 31, 44) (our own arithmetic, not a measured value). On dark designs, rely on a lighter surface colour for elevation (a slightly lighter card) and use shadows for subtle depth, or increase the opacity. Use the Dark preview option to judge this before you copy the code.

A shadow alone is not a reliable signal. Do not make an interactive element identifiable only by its shadow; keep a visible border, label or contrast difference as well, since shadows can disappear in high-contrast or forced-colours modes. The tool runs entirely in your browser: we monitored the network while adding layers and moving sliders and saw no requests with your values, and nothing is stored between visits. Limits to be aware of: there are no presets, no colour output other than rgba(), no way to share a link to your design, and the sliders only move in whole pixels. The Spread slider cannot exceed 30px and the Blur 100px; edit the copied CSS if you need more.

Quick answers

Can I add a shadow to only one side? Yes, with a negative spread and an offset in the direction you want, as described above.

Why does my shadow look cut off? A parent with overflow: hidden clips it, and so does a tight container. Add padding to the parent or move the shadow to a wrapper.

How many layers should I use? Two or three are usually enough. Beyond that the extra layers are hard to tell apart, and each one adds a little painting work.

Can I use the output for an inner glow? Yes: switch Inset on, set X and Y to 0, add blur, and choose a bright colour.

Ready to design a shadow?

Open the Box Shadow Generator