Box Shadow preview

Box Shadow

Design CSS box-shadow effects with visual controls for offset, blur, spread, and color. Supports multiple shadow layers and inset shadows. Copy the generated CSS code directly.

Key features

  • Intuitive horizontal and vertical offset controls
  • Blur and spread radius sliders
  • Both inner (inset) and outer shadow support
  • Copy full CSS code with all necessary formatting

Guide

The CSS box-shadow property adds shadow effects to elements. It is one of the most used CSS properties for creating depth, elevation, and visual hierarchy in user interfaces. Cards, buttons, modals, dropdown menus, navigation bars, tooltips, and floating action buttons all commonly use box-shadow to appear lifted above the surface beneath them. A well-crafted shadow makes the difference between a flat, lifeless interface and one that feels three-dimensional and interactive. The box-shadow property accepts several values in order: horizontal offset, vertical offset, blur radius, spread radius, and color. Here is a basic example: .card { box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); } The horizontal offset (0) means the shadow is directly below the element, not shifted left or right. The vertical offset (4px) pushes the shadow downward by 4 pixels. The blur radius (6px) controls how soft the shadow's edge is. The spread radius (-1px) makes the shadow slightly smaller than the element. The color rgba(0, 0, 0, 0.1) is black at 10% opacity. Understanding each parameter in depth is essential for creating exactly the shadow effect you want. The horizontal offset moves the shadow left (negative values) or right (positive values) relative to the element. A value of 0 means the shadow is centered horizontally behind the element. Typical values range from -20px to 20px. Large offsets create a dramatic, directional look that implies a strong side light. Small offsets (1-4px) create a subtle directional bias that adds realism without being dramatic. For most UI elements, keep the horizontal offset at 0 unless you are deliberately simulating an angled light source. The vertical offset works the same way but moves the shadow up (negative values) or down (positive values). Most natural-looking shadows use a positive vertical offset between 1px and 20px because light typically comes from above, casting shadows downward. Negative vertical offsets can create a top-lit effect where the shadow appears above the element, which is useful for elements that appear to recede into the page rather than float above it. The vertical offset is the primary control for how "high" the element appears to be floating. Blur radius determines the softness of the shadow's edge. A value of 0 creates a sharp-edged shadow with no blur, like a flat copy of the element offset from it. This is useful for creating solid, hard-edged decorative effects. Small values (2-4px) create tight, crisp shadows that suggest the element is close to the surface with a nearby light source. Medium values (8-16px) create the soft shadows you see on modern card designs, suggesting a more distant, diffuse light source. Large values (24-48px) create very soft, ambient shadows that feel like distant, soft light sources illuminating the scene. The blur radius cannot be negative. As a rule of thumb, the blur radius should be roughly 1.5 to 3 times the vertical offset for a natural look. Spread radius controls how much the shadow expands or contracts relative to the element's dimensions. A positive spread makes the shadow larger than the element in all directions. A negative spread makes it smaller. Spread has several practical uses. Positive spread with zero blur and zero offset creates a solid border-like effect (useful for adding a colored outline without changing the element's layout). Negative spread with high blur creates a shadow that is soft but does not extend far beyond the element's edges, keeping the shadow contained. A value of -1px to -4px is common for card shadows to prevent the shadow from looking too wide. The color parameter is where most developers underestimate the visual impact. Pure black shadows (rgba(0, 0, 0, x)) look harsh and unnatural because in the real world, shadows are never pure black. They pick up color from the surface beneath the object and from ambient light. Colored shadows that match the element's background or the surrounding palette look significantly more refined. For a blue card on a white background, a shadow using rgba(59, 130, 246, 0.15) feels more cohesive than a generic black shadow. For a warm-toned section, use a warm shadow color like rgba(120, 80, 40, 0.1). The opacity (alpha value) controls how prominent the shadow is, with values between 0.05 and 0.25 covering most UI use cases. Shadows above 0.3 opacity tend to look heavy. Inset shadows reverse the direction of the effect, making the shadow appear inside the element rather than outside. Add the inset keyword before the values: .input-field { box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.06); } .well { box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.1); background: #f1f5f9; } Inset shadows create a recessed or pressed-in appearance. They are commonly used on input fields to give a sunken feel, on inner containers to create depth, on pressed button states, and on well components (content areas that appear to be cut into the page). Combining an inset shadow with a slightly darker background color creates a convincing pressed-button effect: .button:active { box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15); background-color: #2563eb; transform: translateY(1px); } The transform: translateY(1px) combined with the inset shadow makes the button feel like it is being physically pressed. Layering multiple shadows is where box-shadow becomes truly powerful. CSS allows multiple shadow definitions separated by commas: .card-elevated { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.12), 0 1px 2px rgba(0, 0, 0, 0.24); } The first shadow is a larger, softer ambient shadow that creates a general sense of elevation. The second is a tight, slightly darker shadow close to the element that provides edge definition. Together, they create a more realistic depth effect than any single shadow can achieve. This is because real-world objects cast both a tight shadow directly beneath them and a larger, softer shadow from ambient light. Google's Material Design system uses this dual-shadow approach extensively, and it is one of the reasons Material Design elements look physically believable. Here is a practical elevation system you can use in your projects. These values are battle-tested across thousands of production websites: :root { --shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05); --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1); --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1); --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.1); --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25); --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.05); } .card { box-shadow: var(--shadow-md); } .dropdown { box-shadow: var(--shadow-lg); } .modal { box-shadow: var(--shadow-xl); } .tooltip { box-shadow: var(--shadow-sm); } .input { box-shadow: var(--shadow-inner); } .floating-action-button { box-shadow: var(--shadow-2xl); } This system creates a consistent visual hierarchy. Subtle elements like tooltips sit at low elevation. Cards sit at medium elevation. Dropdowns float above cards. Modals float above everything. Floating action buttons cast the deepest shadows. Users subconsciously understand this layering, and it guides their attention to the most prominent elements. Hover state shadows create interactive feedback. When a user hovers over a card, increasing the shadow makes it feel like the card lifts toward them: .card { box-shadow: var(--shadow-md); transition: box-shadow 0.2s ease, transform 0.2s ease; } .card:hover { box-shadow: var(--shadow-xl); transform: translateY(-2px); } The transition property ensures the shadow change is smooth rather than abrupt. A duration of 150-250ms feels responsive without being jarring. The transform: translateY(-2px) physically moves the card upward, reinforcing the illusion that it is lifting off the page. This combination of increased shadow and upward translation is one of the most common and effective hover effects in modern web design. Performance matters with box-shadow. Changing box-shadow triggers a repaint in the browser, which is more expensive than changes to transform or opacity (which can be composited by the GPU without a repaint). For a few elements, this is not noticeable. For elements with frequent shadow changes, like hover states on a grid of 50 cards, the repaints can accumulate and cause visual stuttering. A performance optimization is to use a pseudo-element for the hover shadow and transition its opacity instead: .card { position: relative; box-shadow: var(--shadow-md); } .card::after { content: ''; position: absolute; inset: 0; border-radius: inherit; box-shadow: var(--shadow-xl); opacity: 0; transition: opacity 0.2s ease; pointer-events: none; } .card:hover::after { opacity: 1; } This approach renders both shadows from the start (no repaint needed) and transitions opacity (which is GPU-composited) instead of box-shadow values. The result is smoother animations even on pages with many cards. Neumorphism is a design trend that relies heavily on box-shadow. It uses light and dark shadows on a colored background to create a soft, embossed or debossed appearance that looks like shapes pushed out of or pressed into a surface: .neumorphic-raised { background: #e0e0e0; border-radius: 16px; box-shadow: 8px 8px 16px #bebebe, -8px -8px 16px #ffffff; } .neumorphic-pressed { background: #e0e0e0; border-radius: 16px; box-shadow: inset 8px 8px 16px #bebebe, inset -8px -8px 16px #ffffff; } The raised example creates an element that appears to protrude from the surface, with a dark shadow on the bottom-right (simulating a top-left light source) and a light highlight on the top-left. The pressed example uses inset shadows for a debossed, pushed-in appearance. Neumorphism looks distinctive but has real accessibility concerns. The low contrast between the element and its background can make interactive elements (buttons, toggles, inputs) hard to identify for users with low vision. If you use neumorphism, add clear focus indicators and consider providing a high-contrast alternative. Dark mode requires shadow adjustments. On light backgrounds, shadows work by darkening the area behind the element. On dark backgrounds, dark shadows are invisible against the already-dark surface. The common approach for dark mode is to increase shadow opacity: [data-theme="dark"] { --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.4), 0 2px 4px -2px rgba(0, 0, 0, 0.3); } Some designers add a subtle light border or glow to dark-mode cards instead of relying solely on shadows. A 1px border with a slightly lighter color than the card background (for example, rgba(255, 255, 255, 0.05)) provides the edge definition that shadows provide in light mode. Some modern dark-mode designs use colored glow effects as shadows: [data-theme="dark"] .card-accent { box-shadow: 0 4px 20px rgba(59, 130, 246, 0.15); } This creates a subtle blue glow beneath the card that looks intentional and adds visual interest to the dark interface. Text shadow is a related but separate CSS property. While box-shadow applies to the rectangular bounding box of an element, text-shadow applies directly to the individual text characters: .heading { text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.3); } .neon-text { text-shadow: 0 0 7px #fff, 0 0 10px #fff, 0 0 21px #fff, 0 0 42px #3b82f6, 0 0 82px #3b82f6; } Text-shadow accepts horizontal offset, vertical offset, blur radius, and color (no spread radius and no inset option). The neon text example layers multiple shadows at increasing blur distances to create a glowing neon sign effect. For filtering and advanced shadow effects, CSS filter: drop-shadow() offers an alternative to box-shadow. The key difference is that drop-shadow follows the actual rendered shape of the element, including transparent areas in PNG images and irregular shapes created by clip-path, while box-shadow always follows the rectangular bounding box: .icon { filter: drop-shadow(0 4px 3px rgba(0, 0, 0, 0.1)); } .custom-shape { clip-path: polygon(50% 0%, 0% 100%, 100% 100%); filter: drop-shadow(0 4px 8px rgba(0, 0, 0, 0.2)); } The drop-shadow on the clipped triangle follows the triangular shape rather than casting a rectangular shadow. This is particularly useful for icons, logos, SVGs, and images with transparent backgrounds where a rectangular shadow would look wrong. Note that filter: drop-shadow does not support spread radius or the inset keyword. Common mistakes to avoid when working with shadows: using too many shadow layers (two or three is usually enough for any effect), using pure black at high opacity (anything above 0.3 tends to look heavy and unnatural), using box-shadow as a replacement for borders (use actual borders or outline for layout borders since they handle border-radius and stacking context differently), forgetting to adjust shadows for dark mode, and applying very large blur values on many elements simultaneously without considering the rendering cost on lower-end mobile devices. Glassmorphism is another shadow-adjacent trend that combines a frosted glass effect with subtle shadows. The technique uses backdrop-filter: blur() with a semi-transparent background and a thin border: .glass-card { background: rgba(255, 255, 255, 0.15); backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); border: 1px solid rgba(255, 255, 255, 0.2); border-radius: 16px; box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); } The box-shadow in glassmorphism is typically soft and subtle, providing just enough depth to lift the glass element off the background. The blur effect handles most of the visual interest. This style works best over colorful or image-based backgrounds where the blur effect has content to distort. For consistent shadows across a design system, document your shadow tokens with visual examples. Create a reference page that shows each shadow level applied to identical card elements side by side. This reference becomes the definitive guide for developers choosing which shadow level to apply. When a developer asks "which shadow should I use for a tooltip?" they can look at the reference and visually match the appropriate elevation. This is far more effective than describing shadows in words or expecting developers to memorize CSS values. Shadow direction should be consistent throughout your interface. If cards cast shadows downward and to the right (positive horizontal and vertical offsets), every element on the page should follow the same light direction. Mixing shadow directions creates an unsettling, physically impossible effect that users may not consciously identify but will feel is "off." The most common and natural shadow direction is straight down (0 horizontal, positive vertical) or slightly to the right (small positive horizontal, larger positive vertical). When combining box-shadow with border-radius, the shadow automatically follows the rounded corners of the element. This works seamlessly for all shadow types including inset. However, if you apply box-shadow to an element with overflow: hidden and child elements that extend to the edges, the inset shadow may be hidden behind the child content. In these cases, use a pseudo-element for the inset shadow or adjust the child element margins. Responsive shadow adjustments are often overlooked. On small mobile screens, large shadows with wide spread and high blur can look disproportionate because the shadow extends beyond the visible area or dominates the compact layout. Consider reducing shadow intensity and size on smaller screens: @media (max-width: 768px) { :root { --shadow-md: 0 2px 4px -1px rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1); --shadow-lg: 0 6px 10px -2px rgba(0, 0, 0, 0.1), 0 3px 4px -3px rgba(0, 0, 0, 0.1); } } This reduces shadow sizes by roughly 40% on mobile devices, keeping the depth effect proportional to the smaller viewport. Shadow tokens in Tailwind CSS follow a similar naming pattern to the custom properties system described above. Tailwind provides shadow-sm, shadow, shadow-md, shadow-lg, shadow-xl, shadow-2xl, shadow-inner, and shadow-none utility classes. You can customize these in your tailwind.config.js: module.exports = { theme: { boxShadow: { sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)', DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.1)', md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -2px rgba(0, 0, 0, 0.1)', colored: '0 4px 14px -3px rgba(59, 130, 246, 0.3)', }, }, } The colored shadow example shows how to add brand-specific shadow tokens to your utility framework. Shadow testing across browsers and operating systems reveals subtle rendering differences. WebKit (Safari) and Blink (Chrome) render blur slightly differently, with Safari producing marginally softer edges. Firefox tends to match Chrome closely. The differences are usually imperceptible at normal blur values (4-20px) but become noticeable with very large blur values (40px+). Test your shadows on at least Chrome, Safari, and Firefox to ensure they look consistent. Mobile browsers generally match their desktop counterparts. Box-shadow and outline interact in specific ways. The CSS outline property renders outside the element's border box, while box-shadow renders outside (or inside, for inset) the border box. If an element has both a visible outline and a box-shadow, the outline appears on top of the shadow. Focus states often use outline for accessibility (it is not clipped by overflow: hidden, unlike box-shadow), so your shadow and focus outline should be visually compatible. A common approach is to use an outline offset to push the focus outline outside the shadow area: .card:focus-visible { outline: 2px solid #3b82f6; outline-offset: 4px; } This places the focus indicator clearly outside the card's shadow, making both the depth effect and the focus state visible without visual conflict. For elements that overlap (like overlapping cards in a stack or an expanding accordion), z-index and shadow work together to establish visual hierarchy. The element with the higher z-index should also have a larger shadow to maintain the illusion of physical depth. If a high-z-index element has a smaller shadow than the element beneath it, the visual hierarchy becomes confusing. The box shadow generator provides visual sliders for every parameter, a live preview that updates as you drag each control, support for multiple shadow layers, inset toggle, and color picker with opacity control. Instead of writing values in code, refreshing the browser, evaluating the result, and adjusting in a loop, you see the effect update in real time as you experiment with different combinations. When the shadow looks right, copy the complete CSS with one click and paste it directly into your stylesheet. This visual approach is significantly faster than manual coding and helps you develop an intuition for which parameter values produce which visual effects.

Frequently asked questions

Can I layer multiple shadows?

Yes! I allow you to define multiple shadow layers, and I'll format them as a single CSS string.

Does it work for text-shadow too?

This tool focuses on box-shadow. You can apply similar values to text-shadow in your CSS.

Related guides

Related WebRecast sections