belun.app Blog
RU

CSS Box Shadow: Offset, Blur, Spread, and Layered Depth

What the four box-shadow values actually do, why blur and spread confuse everyone, and the layering trick behind realistic UI shadows.

Web designer adjusting CSS box shadow styles on a laptop screen

Every CSS developer has typed box-shadow: 0 4px 8px something, squinted at the result, and started changing numbers at random. The property takes up to four lengths plus a color, none of them labeled, and two of them — blur and spread — do things that sound identical until you see them side by side. That’s the whole reason the CSS Box Shadow Generator exists: drag sliders, watch the box, stop guessing.

Still, the numbers are worth understanding once. It takes five minutes and you’ll never squint again.

The four values, in order

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

Reading left to right: horizontal offset, vertical offset, blur radius, spread radius, color. The first two are simple — positive X pushes the shadow right, positive Y pushes it down. Negative values go the other way. Almost every UI shadow uses a small positive Y and zero X, because light in interfaces conventionally comes from above.

Spread is optional and defaults to zero, which is why you see three-value shadows everywhere.

Blur and spread are not the same thing

Blur softens the edge. The shadow stays the same size; its boundary just fades out over a wider band. At blur: 0 you get a hard-edged copy of the box, which almost always looks wrong unless you’re going for a retro poster style.

Spread resizes the shadow itself, before any blurring. Positive spread grows it past the box on all sides. Negative spread shrinks it, tucking the shadow underneath the element.

Negative spread is the underrated one. A big blur with a slightly negative spread gives you softness without the shadow leaking out sideways — the classic floating-card look.

One shadow always looks slightly fake

Look at a real object on your desk. Its shadow has a dark, tight core right at the contact point and a wide, faint halo further out. A single box-shadow can only draw one of those.

Design systems solve this by stacking. Tailwind’s shadow-md is actually two layers:

box-shadow:
  0 4px 6px -1px rgb(0 0 0 / 0.1),
  0 2px 4px -2px rgb(0 0 0 / 0.1);

Material Design goes up to three per elevation level. The pattern is always the same: one small sharp shadow for contact, one large blurry one for ambience. box-shadow accepts any number of comma-separated layers, and the generator has an “Add layer” button for exactly this.

While you’re at it, keep opacity low. Black at 10–30% via rgba() reads as depth; a solid gray shadow reads as a smudge. If your shadow looks dirty, it’s almost always too opaque, not too big.

inset flips the light

Add the inset keyword and the shadow draws inside the element instead of behind it, as if the box were pressed into the page. Text inputs, toggle wells, and pressed-button states are the usual customers. All four length values behave the same; only the direction of the illusion changes.

Two habits worth keeping

Don’t animate box-shadow directly on hover — the browser repaints the blur every frame, and on large elements you’ll feel it. Put the bigger shadow on a pseudo-element and animate its opacity instead.

And when a shadow fights you, rebuild it visually. Open the CSS Box Shadow Generator, set the offset and blur by eye, stack a second layer if the depth feels flat, and copy the finished declaration straight into your stylesheet. Everything runs in your browser, nothing to install.

Try the tool

CSS Box Shadow Generator →