Skip to content

How to stack, tune and copy a box-shadow

The page opens with two shadows on a white preview card: 0px 18px 42px -14px rgba(31, 71, 53, 0.28) and 0px 4px 10px 0px rgba(31, 71, 53, 0.12). The preview and the export panel are the same string, so what you see is what Copy CSS puts on the clipboard.

Each layer keeps its own offset, blur, spread, colour, opacity and inset flag. A new layer is derived from the active one instead of starting blank: Add layer adds 4px to Y, 10px to blur (capped at 200) and takes 0.06 off the opacity (floor 0.05), while spread and colour are copied and inset starts off.

  1. Pick the layer to edit under Active layer, or press Add layer for a third and fourth entry. The picker shows Layer 1 to Layer 4; the fourth is the maximum and the last remaining layer cannot be removed.
  2. Type the horizontal and vertical offset. Both accept -100 to 100px, blur accepts 0 to 200px and spread -100 to 100px. Fractions are kept to one decimal and a value outside its range is written back to the limit when the field loses focus.
  3. Choose the colour in the picker and set the opacity between 0 and 1. Opacity keeps two decimals and is exported inside rgba(): the hex colour becomes 0-255 channels with the alpha you typed.
  4. Tick Inset shadow to move that layer inside the card. The flag belongs to the active layer only, and a newly added layer always starts unchecked.
  5. Press Copy CSS for the whole declaration, or Reset to return to the two starting layers. The clipboard receives the export panel character for character, including the fixed .shadowed-element selector.

Defaults, the four-layer cap and the values written back on commit

Four layers, one declaration

Layers print in the order they appear in the picker, one per line, as a single box-shadow value. The first line is the shadow painted on top: in a pixel probe with a red 24px spread as layer 1 and a blue 12px spread as layer 2, the 0-12px overlap band was red, so later layers only show where the earlier one is smaller or more transparent.

Add layer derives the new entry from the active one (Y + 4px, blur + 10px up to 200, opacity - 0.06 down to 0.05, same spread and colour, inset off). Remove layer deletes the active row and keeps at least one, and the counter reads 1 layer up to 4 layers.

Bounds that are written back on commit

Horizontal and vertical offset -100 to 100, blur 0 to 200, spread -100 to 100 and opacity 0 to 1. While you type, the preview stays inside those bounds; when the field loses focus the rounded value is written back into the field, so the field, the preview and the code panel always agree.

Emptying a field restores the value that was stored before instead of switching it to zero. Fractional pixels keep one decimal (12.5px stays 12.5px) and opacity keeps two; typing x = 999 stores 100px and blur = -10 stores 0px.

What this page does not do

Each layer takes one hex colour; alpha comes from the opacity field, so there is no hsl(), named colour, gradient or second colour input. The exported selector is fixed and the result is a single box-shadow declaration with no CSS variable or per-breakpoint output.

There is no drop-shadow or text-shadow mode, no image or SVG export and no history beyond Reset. Everything is computed in the page: driving every control, adding and removing a layer, copying and resetting sent zero network requests in the probe, and the page keeps working offline.

Recent tools: