HTML Formatterhtmlformatteronline.com

Box shadow generator

Stack layers, adjust them visually, and copy the CSS. Convincing shadows need two or three soft layers rather than one hard one.

Target
Layers

Real shadows are several soft layers, not one hard one. Order is front to back.

XYBlurSpread
Preview
CSS

The four numbers

ValueDoes whatUsually
X offsetMoves the shadow left or right0 — light comes from above, not the side
Y offsetMoves it downPositive, and roughly half the blur
BlurHow soft the edge isThe largest of the four
SpreadGrows or shrinks the shadow before blurring0, or negative to pull it in

Negative spread is the least-used and most useful of the four. It shrinks the shadow so it does not spill out sideways, which is what stops a large blur looking like a halo.

Why one layer never looks right

A real object casts a small, dark, tight shadow where it meets the surface, and a large, faint, diffuse one further out. A single CSS shadow can only be one of those, which is why single-layer shadows look like stickers.

Two layers is the minimum for something convincing. The default above is the pattern most design systems converge on:

A two-layer shadow
.card {
  box-shadow:
    0 1px 2px rgba(16, 27, 45, 0.06),
    0 8px 28px -18px rgba(16, 27, 45, 0.35);
}

The first layer is the contact shadow: barely offset, barely blurred, very subtle. The second is the ambient one: pushed down, heavily blurred, pulled in with negative spread so it stays under the card instead of leaking around it.

Keep the light source consistent

Every shadow on a page should behave as though one light is above it. That means X offset stays at 0 and Y offset stays positive, everywhere, without exception.

What changes between elements is elevation, not direction. A card sitting almost flat gets a small offset and a small blur. A modal floating above everything gets a large offset and a large blur. Define three or four levels, name them, and use only those:

An elevation scale
--shadow-1: 0 1px 2px rgba(16,27,45,.06);
--shadow-2: 0 2px 4px rgba(16,27,45,.06), 0 8px 24px -16px rgba(16,27,45,.3);
--shadow-3: 0 4px 8px rgba(16,27,45,.08), 0 16px 40px -20px rgba(16,27,45,.4);

Ad-hoc shadows are what make an interface feel unplanned. A scale makes depth mean something.

Inset shadows

Add inset and the shadow falls inside the element instead of outside. Three genuine uses:

  • Pressed states. A small inset shadow on :active makes a button feel like it goes in.
  • Input fields. A faint inset shadow at the top reads as recessed, which is the conventional signal for "you can type here".
  • Hairline borders that do not affect layout. inset 0 0 0 1px draws a one-pixel line inside the element without adding to its size the way a real border does.

Dark mode changes the rules

Shadows work by darkening what is behind them. On a dark background there is nothing left to darken, so a shadow that reads as crisp elevation in light mode disappears entirely in dark mode.

Two options. Make the shadows much stronger and much larger — near-black at high opacity, spread wide. Or stop using shadows for depth and use surface lightness instead: raise the background of the elevated element a step, which is how most dark interfaces actually signal layering.

If you use CSS custom properties for your shadows, redefining them inside your dark theme block costs three lines and fixes the whole site at once.

Performance

Static shadows are cheap. Animated ones are not — box-shadow triggers a repaint on every frame, and a large blur radius makes each of those repaints expensive.

For a hover lift, animate transform: translateY() instead, which is GPU-accelerated. If you need the shadow itself to change, stack a pseudo-element with the stronger shadow and animate its opacity — opacity is also GPU-accelerated, so the whole thing stays on the compositor.

A cheap hover lift
.card {
  transition: transform .18s ease;
  box-shadow: 0 1px 2px rgba(16,27,45,.06), 0 8px 28px -18px rgba(16,27,45,.35);
}
.card:hover { transform: translateY(-2px); }

Questions about this generator

Why does my shadow look like a grey box?

Blur is too low for the offset, or opacity is too high. Try roughly doubling the blur relative to the Y offset and dropping the alpha below 0.2. Soft and faint reads as a shadow; hard and dark reads as a second element.

Should shadows be black?

Rarely. Pure black at low opacity turns everything under it grey. Tinting the shadow toward your background's hue — a deep navy on a cool interface, a warm brown on a cream one — looks noticeably more natural. The default above uses a dark navy for this reason.

What is the difference between box-shadow and drop-shadow?

box-shadow follows the element's box, so a transparent PNG gets a rectangular shadow. filter: drop-shadow() follows the actual shape, including transparency, which is what you want for logos and irregular SVG. It is more expensive to render and takes no spread value.

How many layers is too many?

Three or four is plenty for anything. Beyond that you are adding paint cost for a difference nobody can see. If a shadow is not landing, the fix is usually the ratio between blur and offset, not another layer.

Do shadows affect layout?

No. A shadow paints outside the element without occupying space, so it never pushes anything around — which also means it can be clipped by a parent with overflow: hidden. That is the usual reason a shadow mysteriously vanishes on one side.

Related tools

Learn the why, not just the how

Longer reading on formatting, indentation and minification.