Free · Fast · Privacy-first

CSS Button Shadow Generator

A well-designed button shadow does three jobs at once.

Build resting, hover, and active shadow states visually

🔒

Live preview showing all three button states

Proportionally sized shadow values for small elements

Exports CSS for all three states ready to copy

Cost
Free forever
Sign-up
Not required
Processing
In your browser
Privacy
Files stay local
FreeNo signupWhite-label

Add this Shadow Effect Builder to your website

Drop the Shadow Effect Builder into any page — blog post, product docs, intranet, school portal — with a single line of HTML. Your visitors get the full tool, processed entirely in their browser. No backend, no uploads, no signup.

  • Files stay 100% in the visitor's browser
  • Responsive — adapts to any container width
  • Free forever, no API key needed

Embed code

<iframe
  src="https://www.fixtools.io/css-tool/shadow-effect-builder?embed=1"
  width="100%"
  height="780"
  frameborder="0"
  style="border:0;border-radius:16px;max-width:900px;"
  title="Shadow Effect Builder by FixTools"
  loading="lazy"
  allow="clipboard-write"
></iframe>

Attribution-friendly: a small "Powered by FixTools" link appears in the embed footer.

Why Buttons Need Distinct Shadow States and How Small Values Make the Biggest Difference

A shadow on a button does more than add visual depth. It communicates to the user that the element is clickable before any interaction occurs. A flat element without shadow can look like a label or a decoration; a button with even a subtle 2px shadow reads as a raised, pressable surface. Research in interaction design consistently shows that affordance cues such as shadow elevation reduce the cognitive effort users need to identify interactive elements on a page. This is particularly important on pages with mixed content where some text or images might look button-like without actually being interactive.

The three-state shadow pattern is the foundation of expressive button interaction. In the resting state, a small but visible shadow places the button slightly above the background. On hover, the shadow deepens and optionally a translateY(-1px) transform lifts the button slightly, suggesting it is rising to meet the cursor. In the active or pressed state, the shadow is reduced to near-zero or replaced with an inset shadow, suggesting physical depression. The entire sequence communicates the physical metaphor of pressing a button. The key constraint for buttons is that all shadow values must be proportionally small. A 32px tall button with a 20px blur shadow looks top-heavy and unfocused.

Shadow values for small buttons should stay firmly at the low end of the available range. Use a 1 to 2 pixel vertical offset and 4 to 6 pixel blur at rest, increasing to 3 to 4 pixels of offset and 8 to 12 pixels of blur on hover for a clear but proportional lift. Button background colour affects the shadow choice as well. A dark button pairs naturally with a dark shadow at medium opacity, which is nearly invisible against the button itself but still present in the contact zone where it meets the surrounding surface. A light button on a white background benefits from slightly higher shadow opacity, around rgba(0,0,0,0.15) to rgba(0,0,0,0.2), to maintain the contrast needed for the elevation cue to read at typical viewing distances.

Button shadow also needs to coordinate with the rest of the elevation system on the page rather than being designed in isolation. If your cards rest at a shadow depth of 0 2px 4px and your modals sit at 0 16px 40px, the primary CTA button should land between those tiers rather than competing with either one. A button shadow stronger than the card it sits inside makes the button look unmoored from the surface, while a button shadow weaker than nearby decorative chrome can make the action feel less important than it is. Treat the button as one component within a coherent elevation scale and tune its three states accordingly so the entire page reads as a single integrated system rather than a collection of disconnected parts.

How to use this tool

💡

Build the resting state shadow first with a small offset and moderate blur. Duplicate it and increase the offset and blur for the hover state. Create the active state by switching to inset shadow or reducing the outer shadow significantly.

How It Works

Step-by-step guide to css button shadow generator:

  1. 1

    Build the resting state shadow

    Set a small vertical offset of 1 to 2 pixels and a moderate blur of 4 to 6 pixels for the button at rest, with shadow opacity around 0.12 to 0.18 on a white background. This baseline shadow should be visible enough to communicate clickability immediately but subtle enough that it does not pull attention away from surrounding content or compete with adjacent UI components on the page when no interaction is occurring yet.

  2. 2

    Create the hover state

    Increase the vertical offset to 3 to 4 pixels and the blur to 8 to 12 pixels for the hover state, optionally pairing the deeper shadow with a transform: translateY(-1px) so the button physically rises slightly to meet the cursor. The combined lift and shadow change reads as a single coherent interaction signal. Always animate both properties together using a single transition declaration with matched duration and easing to keep the movement coordinated.

  3. 3

    Define the active/pressed state

    Reduce the resting shadow significantly down to roughly 0 1px 2px or switch to a small inset shadow such as inset 0 2px 4px rgba(0,0,0,0.15) for the :active state to simulate the button being physically pressed into the surface. Combine the shadow reduction with a translateY(1px) transform in the same direction as the original offset so the entire press metaphor remains internally consistent across the three-state interaction sequence.

  4. 4

    Copy the CSS for all three states

    Click Copy CSS to copy the generated declarations for each state, then apply each block to your button's resting selector, :hover pseudo-class rule, and :active pseudo-class rule respectively. Add a single transition: box-shadow 0.15s ease, transform 0.15s ease declaration on the base button rule so the interpolation between states animates smoothly without per-state transition redefinition or duplication.

Real-world examples

Common situations where this approach makes a real difference:

Primary CTA button on a landing page

A developer adds a coloured shadow to the primary sign-up button on a SaaS landing page using box-shadow: 0 4px 14px rgba(59,130,246,0.4) on a saturated blue button. The coloured shadow creates a subtle glow that draws the eye to the CTA without increasing the button size or adding a decorative border that would compete with the hero copy. On hover the shadow deepens to 0 6px 20px at higher opacity, reinforcing the lift cue and confirming clickability the moment the cursor approaches the action zone.

Form submit button with three interaction states

A form designer implements all three shadow states on the submit button at the bottom of a multi-step form to communicate progress clearly. At rest the button carries a 2 pixel offset and 6 pixel blur for a quiet but visible elevation. On hover the shadow shifts to a 4 pixel offset and 12 pixel blur with a 1 pixel upward translateY. On active the outer shadow is removed entirely and an inset 0 2px 4px rgba(0,0,0,0.15) shadow is added instead. The full animation sequence takes 150 milliseconds, giving clear and responsive feedback at each interaction phase without feeling slow.

Icon-only action buttons in a toolbar

A developer styles icon buttons in an editor toolbar with subtle shadows: 0 1px 3px rgba(0,0,0,0.1) at rest, scaled down from the values used elsewhere in the app to match the small button footprint. On hover, the shadow increases gently and the background lightens at the same time to reinforce the affordance. On active, the shadow disappears entirely and the background darkens to confirm the click. The minimal shadow distinguishes the interactive buttons from neighbouring static icons in the same toolbar without adding overall visual weight to the chrome.

E-commerce add-to-cart button with physical press feel

A developer adds a brief scale animation to the add-to-cart button on successful click that runs after the cart update request completes. The box-shadow deepens slightly during the downward press phase and lightens again as the button rebounds upward, reinforcing the physical press metaphor with synchronised shadow and transform changes. The combined animation takes 0.3 seconds end to end, well within the perceptual threshold for instant feedback. The polish makes the interaction confirmation feel satisfying and deliberate, encouraging the next purchase action without using a popup or modal confirmation that would interrupt the shopping flow.

When to use this guide

Use this when styling button components and you need precise shadow values for resting, hover, and active states to communicate interactivity clearly.

Pro tips

Get better results with these expert suggestions:

1

Use coloured shadows to make primary buttons pop

A primary action button in a brand colour can use a shadow derived from that same colour rather than a generic black. box-shadow: 0 4px 12px rgba(37,99,235,0.35) on a blue button creates a coloured halo effect that makes the button noticeably more prominent on the page without needing to enlarge the button or add a thick border. The coloured shadow ties the visual emphasis to the brand identity and reads as a deliberate design choice instead of a default neutral elevation. This works particularly well on dark or saturated backgrounds.

2

Remove shadow on :active rather than switching to inset

For small buttons, switching abruptly to an inset shadow on the :active state can read as visually jarring because the rectangular inner darkness appears suddenly with no transitional cue. Reducing the outer shadow to near zero, such as 0 1px 2px rgba(0,0,0,0.1), is often cleaner and reads as pressed without the awkward switch between outer and inset shadow types. Combine the reduced shadow with a small translateY of 1 to 2 pixels in the same direction as the original offset for a more natural physical press feel.

3

Add focus ring alongside shadow for accessibility

Button shadows alone do not meet WCAG 2.1 success criterion 2.4.7, which explicitly requires a visible focus indicator distinct from a hover or resting state. Always add an outline or a distinct :focus-visible rule alongside your shadow styling so keyboard users see a clear cue when the button receives focus. The shadow handles resting and hover affordance, while the dedicated outline or focus ring handles keyboard focus communication independently. A 2 to 3 pixel solid ring at the brand colour, offset by 2 pixels, is the most common reliable pattern.

4

Synchronise CTA button shadow with hero card elevation

If your page contains hero cards with specific elevation shadows that establish the resting depth of the layout, set the primary CTA button shadow to one tier higher than the card resting state. This deliberate spatial hierarchy places the button visually above the card surface inside which it sits, making it feel like the most accessible and immediately actionable element on the card. Without this small offset, the CTA can look embedded in the card rather than emerging from it, weakening the conversion cue at exactly the moment the user is closest to acting.

5

Keep button shadows proportional to button size

A 36px button should use offset values of 1-2px and blur of 4-6px. Larger blurs than this make small buttons look like they are surrounded by haze rather than floating slightly above the background.

6

Use transition: box-shadow, transform together

Animate both box-shadow and transform in a single transition declaration so hover lift and shadow deepening happen simultaneously. Animating one without the other looks disconnected.

7

Test shadows on your actual button colour

Shadow visibility depends heavily on the button background colour relative to the page background. Always test on the real button colour in its actual context, not on a white preview background.

FAQ

Frequently asked questions

For a primary button in the typical 36 to 44 pixel height range, a reliable starting point is the following three-state shadow set. The resting state uses box-shadow: 0 2px 6px rgba(0,0,0,0.15). The hover state uses 0 4px 12px rgba(0,0,0,0.2). The active state uses 0 1px 3px rgba(0,0,0,0.1). For a coloured primary button in a brand hue, replace the rgba black with an rgba version of the button colour at 0.3 to 0.4 opacity for a more cohesive branded shadow that ties the elevation cue back to the button itself. The values can be tuned upward slightly for larger hero CTAs or downward for compact in-card buttons.
The right answer depends on the button size and overall visual style of the surrounding interface. Inset shadows on :active work well for large buttons of 48 pixels and above where there is enough internal surface area for the inner shadow to read clearly without looking pinched. For smaller buttons in the 32 to 40 pixel range, a simpler approach is to reduce the outer shadow significantly and add a slight downward translateY to simulate the press without switching shadow type at all. The shadow-type switch can read as abrupt on small components because the visual change is large relative to the button size. Both patterns are valid, and the choice should be guided by your existing component library conventions.
You can, but box-shadow is generally preferred for rectangular and rounded-rectangular buttons because it gives you spread support, inset support, and the cleanest performance profile for animated states. Filter: drop-shadow() becomes more useful when the button has an irregular shape, a notched cutout, an SVG-based morphing border, or a transparent area inside the button geometry. For the vast majority of standard button shapes including pill buttons, rounded rectangles, and circular icon buttons, box-shadow is more controllable, more interpolatable in transitions, and does not introduce the GPU layer promotion cost that the filter property triggers for every element that uses it.
Yes, almost always. Dark backgrounds make dark shadows essentially invisible against the surrounding chrome, so the resting elevation cue evaporates if the same light-mode shadow values carry over directly. In dark mode, button elevation is often communicated through surface colour brightness rather than shadow alone, lifting the button with a slightly lighter background against a very dark surrounding surface. If shadows are still used in dark mode, increase the opacity significantly compared to the light-mode equivalent, often to rgba(0,0,0,0.4) or higher, to maintain a recognisable elevation cue. Some systems also switch to subtle white inner highlight shadows in dark mode to imply elevation through reflected light rather than absorbed shadow.
Ghost buttons can have shadows, but the visual result is qualitatively different from filled buttons. A shadow on an outline button adds depth to the border itself, making the entire ring more visually prominent and slightly more substantial against the page. However, the combination of a visible outline border and a shadow can look unnecessarily busy on small buttons or in dense layouts where many buttons sit close together. Many modern design systems omit shadows from ghost buttons entirely and rely on the border alone for the raised appearance, reserving shadow treatments for filled primary and secondary buttons. This convention keeps the visual hierarchy between filled and ghost buttons clearly readable across every component in the system.
No, box-shadow is purely a visual property and does not expand the button's clickable hit area in any way. The hit area is determined entirely by the element's own dimensions and padding, which together compose the bounding box that registers pointer and touch events. If you need a larger hit area for accessibility or touch ergonomics, increase the padding inside the button, use the min-height and min-width properties to enforce a comfortable target size, or extend a transparent pseudo-element across a larger zone. The shadow extends visually beyond the click boundary, which is intentional and gives the elevation cue its perceived depth without inflating the registered interactive surface.
Remove or significantly reduce the shadow entirely on disabled buttons, alongside the other disabled-state styling. A typical pattern looks like .button:disabled { box-shadow: none; opacity: 0.5; cursor: not-allowed; pointer-events: none; }. A disabled button should have no elevation shadow because shadow communicates interactivity affordance, and a disabled button is by definition not interactive. Removing the shadow alongside reducing opacity and changing the cursor clearly signals the disabled state to sighted users without relying on a single cue. The same logic applies to loading states, where a busy button should also drop its elevation shadow to reduce visual emphasis until the operation completes and the button returns to its active state.
Not under typical use patterns. Shadow transitions on individual buttons are composited on the GPU in every modern browser and do not trigger layout reflow at any point in the animation lifecycle. They are unlikely to affect Cumulative Layout Shift or Interaction to Next Paint scores noticeably. The main risk emerges when a very large number of shadow-animated buttons are visible and animating simultaneously during a single interaction, which can cause frame drops on low-end mobile devices with constrained GPU memory budgets. For typical product interfaces with a handful of animated buttons per viewport, shadow animations remain one of the cheapest polish techniques available without measurable Core Web Vitals impact in real-world conditions.
Apply a single transition declaration to the base button selector that covers both box-shadow and transform together: transition: box-shadow 0.15s ease, transform 0.15s ease. Matching the duration and easing for both properties keeps the lift movement and the shadow deepening locked together in time, which is essential because human perception immediately notices when one property arrives slightly later than the other. Avoid using transition: all because it animates every animatable property including ones you may not want changing, which can introduce surprising side effects when other styles are adjusted later. Explicitly listing the properties you intend to animate is more maintainable and easier to reason about.
Generally no, because icon-only buttons are smaller in absolute pixel area and need proportionally smaller shadows to look right within the surrounding layout. A 40 by 40 pixel icon button with a shadow tuned for a 120 pixel wide text button will appear smothered in haze, losing crispness around the icon glyph itself. Reduce the shadow offset to 1 pixel and the blur to roughly 3 to 5 pixels for icon-only buttons. The hover state can still deepen proportionally but should remain noticeably tighter than the equivalent text-button hover treatment. Keeping shadow scale proportional to component size is one of the most reliable techniques for keeping a button family looking coherent across every variant.

Related guides

More use-case guides for the same tool:

Ready to get started?

Open the full Shadow Effect Builder — free, no account needed, works on any device.

Open Shadow Effect Builder →

Free · No account needed · Works on any device