Tailwind CSS 23 🎨 Box Shadows, Drop Shadows, and Inset Shadow Styles
A shadow is a lie about light. It suggests depth, elevation, and hierarchy on a flat screen. It is one of the most effective tools for communicating which elements float above others and which sit recessed within a surface. Tailwind provides three distinct shadow mechanisms: shadow-* for box shadows, drop-shadow-* for filter-based shadows that follow irregular shapes, and inset-shadow-* for shadows drawn inside an element. They look similar in a screenshot but behave differently under the hood, and choosing the wrong one produces either the wrong visual effect or a performance penalty.
This chapter covers all three. You will learn the default shadow scale, how to apply shadows conditionally on hover and focus, how drop shadows differ from box shadows in what they follow, and how to create custom shadow values when the defaults are not enough. You will also see the shadow color utilities introduced in Tailwind v4.1 and how they change the way shadows can be styled.
Key point: Box shadows and inset shadows are part of the box-shadow CSS property. Drop shadows are a filter function. Box shadows follow the element’s border box, including its border radius. Drop shadows follow the shape of the element’s rendered content, including transparent regions and irregular shapes.
Why three shadow types exist
The elevation problem. Interfaces need to communicate hierarchy. A modal floats above a page. A dropdown floats above a button. A card sits slightly above its background. Box shadows express this hierarchy by drawing a shadow outside the element, offset and blurred to simulate light from above. The shadow-* scale provides a set of elevation levels, from shadow-sm for subtle lift to shadow-2xl for dramatic emphasis .
The shape problem. Box shadows follow the element’s rectangular border box. This is correct for cards, buttons, and modals. It is wrong for text, SVG icons, and images with transparent regions. A box shadow on transparent text produces a rectangle behind the letters. A drop shadow, by contrast, follows the rendered shape of the element, including its transparency, producing a shadow that traces the actual visible content .
The recession problem. Sometimes an element should appear pressed into its surface rather than floating above it. An input field, a well, or a pressed button benefits from an inset shadow—a shadow drawn inside the element’s border, making the surface appear to curve inward. The shadow-inner utility provides a default inset shadow, and arbitrary values allow custom inset shadows for more control .
The color problem. Before Tailwind v4.1, shadows were always the color specified in the shadow’s CSS value—usually black with some opacity. There was no way to change the shadow color without replacing the entire shadow definition. Tailwind v4.1 added shadow-{color} utilities that let you tint a shadow independently of its geometry, and drop-shadow-{color} utilities for colored drop shadows .
The performance problem. Box shadows are generally cheaper to render than drop shadows because they are rectangular and can be optimized by the browser. Drop shadows require the browser to compute the alpha channel of the element’s rendered content, which is more expensive. For regular elements, box shadows are the right choice. For text and irregular shapes, drop shadows are the only option that produces the correct result.
a. Box shadows: the shadow-* scale
Box shadows are the primary shadow mechanism in Tailwind. The default scale provides six elevation levels and one inset shadow.
<div class="shadow-sm">Subtle</div>
<div class="shadow">Default</div>
<div class="shadow-md">Medium</div>
<div class="shadow-lg">Large</div>
<div class="shadow-xl">Extra large</div>
<div class="shadow-2xl">Maximum</div>
The values progress from a tight, low-opacity shadow to a large, diffuse one. shadow-sm uses a single layer with a 1px vertical offset and 2px blur. shadow-2xl uses a single layer with a 25px vertical offset and 50px blur . The intermediate levels use two layers to produce a more natural falloff.
Shadows compose with other utilities. A card might combine rounded-lg, border, and shadow-md. The shadow follows the border radius automatically because box-shadow respects border-radius .
Conditional shadows are applied with variant prefixes. The most common are hover:shadow-lg for interactive elements and focus:shadow-lg for focus states .
<button class="shadow hover:shadow-lg transition-shadow">
Hover me
</button>
The transition-shadow utility animates the shadow change over 150ms, which is usually enough to make the hover feel responsive without being slow .
Arbitrary values allow one-off shadows that are not part of the theme:
<div class="shadow-[0_35px_60px_-15px_rgba(0,0,0,0.3)]">
The underscores in the arbitrary value are converted to spaces by Tailwind, producing the CSS value 0 35px 60px -15px rgba(0,0,0,0.3) .
b. Drop shadows: shadowing irregular shapes
Drop shadows use the CSS filter property with the drop-shadow() function. They are applied with the drop-shadow-* utilities.
<div class="drop-shadow-sm">Subtle</div>
<div class="drop-shadow">Default</div>
<div class="drop-shadow-md">Medium</div>
<div class="drop-shadow-lg">Large</div>
<div class="drop-shadow-xl">Extra large</div>
<div class="drop-shadow-2xl">Maximum</div>
The visual difference from box shadows is most obvious with transparent or irregular content. A drop shadow applied to text traces the letters. A drop shadow applied to an SVG icon traces the icon’s shape. A drop shadow applied to a PNG with transparency traces the visible content, not the bounding box .
Drop shadows are the correct choice when:
- The element has transparent regions.
- The element is text or an inline SVG.
- The element has a non-rectangular shape.
- The shadow should follow the actual rendered content.
Drop shadows are the wrong choice when:
- The element is a regular rectangular block (card, button, modal).
- Performance is a concern for a large number of elements.
- The shadow should follow the border radius rather than the content shape.
Tailwind v4.1 added colored drop shadows. The syntax is drop-shadow-{color}:
<div class="drop-shadow-indigo-500">Colored shadow</div>
<div class="drop-shadow-cyan-500/50">Semi-transparent</div>
The opacity modifier works as it does with other color utilities. This is useful for branding or for matching a shadow to a background color .
c. Inset shadows and shadow colors
Inset shadows are drawn inside the element’s border. They make the element appear recessed. Tailwind provides shadow-inner as a default inset shadow.
<div class="shadow-inner">Recessed</div>
The default inset shadow is inset 0 2px 4px 0 rgba(0,0,0,0.06) . It is subtle and intended for form inputs, wells, and pressed states.
Custom inset shadows use arbitrary values with the inset keyword:
<div class="shadow-[inset_0_-2px_4px_rgba(0,0,0,0.6)]">
The inset keyword must be the first token in the arbitrary value. Tailwind does not provide a shadow-inner-{size} scale because inset shadows are less common than outer shadows and usually require custom values .
Tailwind v4.1 added shadow color utilities that work with both outer and inset shadows. The syntax is shadow-{color} for outer shadows and inset-shadow-{color} for inset shadows:
<div class="shadow-lg shadow-blue-500/50">Blue shadow</div>
<div class="inset-shadow-md inset-shadow-red-500/30">Red inset</div>
The opacity modifier is supported, allowing shadows to be tinted with the theme palette. This is a change from earlier versions where shadow colors were baked into the shadow definition .
A note on transitions: the inset-shadow-none utility was fixed in a recent Tailwind release to include the inset keyword in its output. Without this, transitions between inset and non-inset shadows do not interpolate smoothly because CSS cannot animate between different shadow types. If you are using a version before this fix, transitions involving inset shadows may behave unexpectedly .
Complete Example Session
<!-- ============================================ -->
<!-- PART 1: BASIC BOX SHADOW SCALE -->
<!-- ============================================ -->
<div class="shadow-sm p-4 bg-white rounded">Subtle</div>
<div class="shadow p-4 bg-white rounded">Default</div>
<div class="shadow-md p-4 bg-white rounded">Medium</div>
<div class="shadow-lg p-4 bg-white rounded">Large</div>
<div class="shadow-xl p-4 bg-white rounded">Extra large</div>
<div class="shadow-2xl p-4 bg-white rounded">Maximum</div>
<!-- ============================================ -->
<!-- PART 2: SHADOW ON HOVER -->
<!-- ============================================ -->
<button class="shadow hover:shadow-lg transition-shadow px-4 py-2 rounded">
Hover me
</button>
<!-- ============================================ -->
<!-- PART 3: SHADOW ON FOCUS -->
<!-- ============================================ -->
<input class="shadow-sm focus:shadow-md transition-shadow border rounded px-3 py-2" />
<!-- ============================================ -->
<!-- PART 4: INSET SHADOW -->
<!-- ============================================ -->
<div class="shadow-inner p-4 rounded bg-gray-50">Recessed</div>
<input class="shadow-inner border rounded px-3 py-2" />
<!-- ============================================ -->
<!-- PART 5: CUSTOM INSET SHADOW -->
<!-- ============================================ -->
<div class="shadow-[inset_0_-2px_4px_rgba(0,0,0,0.6)] p-4">
Custom inset
</div>
<!-- ============================================ -->
<!-- PART 6: DROP SHADOW ON TEXT -->
<!-- ============================================ -->
<h1 class="drop-shadow-lg text-4xl font-bold">Shadowed text</h1>
<!-- ============================================ -->
<!-- PART 7: DROP SHADOW ON SVG -->
<!-- ============================================ -->
<svg class="drop-shadow-md" viewBox="0 0 24 24">
<path d="..." />
</svg>
<!-- ============================================ -->
<!-- PART 8: COLORED DROP SHADOW (v4.1+) -->
<!-- ============================================ -->
<div class="drop-shadow-indigo-500">Colored drop shadow</div>
<div class="drop-shadow-cyan-500/50">Semi-transparent</div>
<!-- ============================================ -->
<!-- PART 9: COLORED BOX SHADOW (v4.1+) -->
<!-- ============================================ -->
<div class="shadow-lg shadow-blue-500/50 p-4 rounded">Blue shadow</div>
<div class="shadow-lg shadow-red-500/30 p-4 rounded">Red shadow</div>
<!-- ============================================ -->
<!-- PART 10: ARBITRARY BOX SHADOW -->
<!-- ============================================ -->
<div class="shadow-[0_35px_60px_-15px_rgba(0,0,0,0.3)] p-4 rounded">
Custom shadow
</div>
The ten parts covered the essential patterns: the box shadow scale, hover shadows, focus shadows, inset shadows, custom inset shadows, text drop shadows, SVG drop shadows, colored drop shadows, colored box shadows, and arbitrary values.
Quick Reference
Box Shadow Scale
| Class | CSS Value | Use Case |
|---|---|---|
shadow-sm | 0 1px 2px 0 rgb(0 0 0 / 0.05) | Subtle lift |
shadow | 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1) | Default |
shadow-md | 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1) | Medium elevation |
shadow-lg | 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1) | Floating |
shadow-xl | 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1) | Modal |
shadow-2xl | 0 25px 50px -12px rgb(0 0 0 / 0.25) | Dramatic |
shadow-inner | inset 0 2px 4px 0 rgb(0 0 0 / 0.05) | Recessed |
shadow-none | 0 0 #0000 | Remove |
Drop Shadow Scale
| Class | CSS Value |
|---|---|
drop-shadow-sm | drop-shadow(0 1px 1px rgb(0 0 0 / 0.05)) |
drop-shadow | drop-shadow(0 1px 2px rgb(0 0 0 / 0.1)) drop-shadow(0 1px 1px rgb(0 0 0 / 0.06)) |
drop-shadow-md | drop-shadow(0 4px 3px rgb(0 0 0 / 0.07)) drop-shadow(0 2px 2px rgb(0 0 0 / 0.06)) |
drop-shadow-lg | drop-shadow(0 10px 8px rgb(0 0 0 / 0.04)) drop-shadow(0 4px 3px rgb(0 0 0 / 0.1)) |
drop-shadow-xl | drop-shadow(0 20px 13px rgb(0 0 0 / 0.03)) drop-shadow(0 8px 5px rgb(0 0 0 / 0.08)) |
drop-shadow-2xl | drop-shadow(0 25px 25px rgb(0 0 0 / 0.15)) |
Shadow Color Utilities (v4.1+)
| Class | Effect |
|---|---|
shadow-{color} | Tint outer box shadow |
shadow-{color}/{opacity} | With opacity modifier |
drop-shadow-{color} | Tint drop shadow |
inset-shadow-{color} | Tint inset shadow |
When to Use Each
| Shadow Type | Element Type | Follows |
|---|---|---|
shadow-* | Rectangular blocks | Border box |
drop-shadow-* | Text, SVG, transparent images | Rendered content |
shadow-inner | Inputs, wells, pressed states | Inside border |
Best Practices
✅ Do This:
<!-- Use box shadow for cards and buttons -->
<div class="shadow-md rounded-lg p-6">Card</div> <!-- ✅ -->
<!-- Use drop shadow for text and SVG -->
<h1 class="drop-shadow-lg">Title</h1> <!-- ✅ -->
<!-- Transition shadow changes -->
<button class="shadow hover:shadow-lg transition-shadow"> <!-- ✅ -->
<!-- Use inset for form inputs -->
<input class="shadow-inner border rounded" /> <!-- ✅ -->
<!-- Use colored shadows for branding -->
<div class="shadow-lg shadow-blue-500/50">Branded</div> <!-- ✅ -->
<!-- Use arbitrary values for one-off shadows -->
<div class="shadow-[0_10px_40px_-10px_rgba(0,0,0,0.3)]"> <!-- ✅ -->
❌ Don’t Do This:
<!-- Don't use box shadow on transparent text -->
<h1 class="shadow-lg">Text</h1> <!-- ❌ -->
<!-- Don't use drop shadow on cards -->
<div class="drop-shadow-md p-6">Card</div> <!-- ⚠️ works but slower -->
<!-- Don't forget transition for hover shadows -->
<button class="shadow hover:shadow-lg"> <!-- ⚠️ abrupt -->
<!-- Don't use inset shadow for elevation -->
<div class="shadow-inner">Floating card</div> <!-- ❌ wrong metaphor -->
<!-- Don't use shadow-none without a reason -->
<div class="shadow-none"> <!-- ⚠️ only to remove existing -->
<!-- Don't use arbitrary inset without the inset keyword -->
<div class="shadow-[0_-2px_4px_rgba(0,0,0,0.6)]"> <!-- ❌ not inset -->
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
| Shadow appears as rectangle | Box shadow on transparent text | Use drop-shadow-* |
| Shadow doesn’t follow shape | Box shadow on SVG | Use drop-shadow-* |
| Hover shadow is abrupt | No transition-shadow | Add transition class |
| Inset arbitrary value ignored | Missing inset keyword | Start with inset_ |
| Shadow color not changing | No color utility | Use shadow-{color} in v4.1+ |
| Performance issue with many elements | Drop shadow on large list | Use box shadow for rectangles |
| Transition between inset types broken | Old version bug | Update Tailwind |
Real-World Examples
1. Card with Hover Lift
<div class="shadow-md hover:shadow-xl transition-shadow rounded-lg p-6">
Card content
</div>
2. Modal Dialog
<div class="shadow-2xl rounded-xl bg-white p-8">
Modal content
</div>
3. Text with Drop Shadow
<h1 class="drop-shadow-lg text-5xl font-bold text-white">
Hero Title
</h1>
4. Inset Input Field
<input class="shadow-inner border rounded-lg px-4 py-2" />
5. Pressed Button State
<button class="shadow-md active:shadow-inner transition-shadow">
Press me
</button>
6. Colored Brand Shadow
<button class="shadow-lg shadow-indigo-500/50 bg-indigo-500 text-white">
Branded
</button>
7. Floating Action Button
<button class="shadow-xl hover:shadow-2xl transition-shadow rounded-full p-4">
+
</button>
8. Drop Shadow on Logo
<img class="drop-shadow-md" src="logo.svg" alt="Logo" />
9. Depth on Dark Background
<div class="shadow-lg shadow-black/50 bg-gray-800 rounded-lg p-6">
Dark card
</div>
10. Subtle Elevation
<div class="shadow-sm border rounded-lg p-4">
Subtle card
</div>
Visual
Box Shadow vs Drop Shadow
┌─────────────────────────────────────────────────────────────┐
│ BOX SHADOW (Follows Border Box) │
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ Element (rectangular) │ │
│ │ ┌─────────────────────────────────────────┐ │ │
│ │ │ Text or content │ │ │
│ │ └─────────────────────────────────────────┘ │ │
│ └───────────────────────────────────────────────┘ │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓ Shadow follows the rectangle, not the content ▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ │
├─────────────────────────────────────────────────────────────┤
│ │
│ DROP SHADOW (Follows Rendered Content) │
│ │
│ ┌───────────────────────────────────────────────┐ │
│ │ TEXT │ │
│ │ ╱ ╲ │ │
│ │ ╱ ╲ │ │
│ └───────────────────────────────────────────────┘ │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓ Shadow follows the letters, not a box ▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ │
└─────────────────────────────────────────────────────────────┘
Shadow Scale Progression
┌─────────────────────────────────────────────────────────────┐
│ ELEVATION SCALE │
│ │
│ shadow-sm ▓▓▓ Low, tight │
│ shadow ▓▓▓▓▓ Subtle lift │
│ shadow-md ▓▓▓▓▓▓▓ Medium │
│ shadow-lg ▓▓▓▓▓▓▓▓▓▓ Floating │
│ shadow-xl ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ Modal │
│ shadow-2xl ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ Dramatic │
│ │
│ As elevation increases, offset and blur increase, │
│ and opacity usually increases as well. │
│ │
└─────────────────────────────────────────────────────────────┘
Inset Shadow Effect
┌─────────────────────────────────────────────────────────────┐
│ OUTER SHADOW (Elevation) │
│ │
│ ┌───────────────────────┐ │
│ │ │ │
│ │ Element │ │
│ │ │ │
│ └───────────────────────┘ │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ ▓▓ Shadow outside, element floats above surface ▓▓ │
│ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ │
│ │
├─────────────────────────────────────────────────────────────┤
│ │
│ INSET SHADOW (Recession) │
│ │
│ ┌───────────────────────┐ │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │
│ │▓ ▓▓▓│ │
│ │▓ Element ▓▓▓│ │
│ │▓ ▓▓▓│ │
│ │▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓│ │
│ └───────────────────────┘ │
│ │
│ Shadow inside, element appears pressed into surface. │
│ │
└─────────────────────────────────────────────────────────────┘
Shadow Composition
┌─────────────────────────────────────────────────────────────┐
│ SHADOW LAYERS │
│ │
│ A box-shadow can have multiple layers: │
│ │
│ box-shadow: │
│ 0 1px 3px 0 rgb(0 0 0 / 0.1), ← layer 1 (closest) │
│ 0 1px 2px -1px rgb(0 0 0 / 0.1); ← layer 2 │
│ │
│ Tailwind's shadow utilities encode multiple layers │
│ for realistic falloff. │
│ │
│ Rings, inset shadows, and regular shadows can all │
│ be combined on the same element through CSS variables. │
│ │
└─────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Box shadow | shadow-{size} for elevation |
| Box shadow scale | sm, “ (default), md, lg, xl, 2xl |
| Inset shadow | shadow-inner for recession |
| Drop shadow | drop-shadow-{size} for irregular shapes |
| Shadow color | shadow-{color} (v4.1+) |
| Drop shadow color | drop-shadow-{color} (v4.1+) |
| Hover variant | hover:shadow-lg |
| Focus variant | focus:shadow-md |
| Transition | transition-shadow |
| Remove shadow | shadow-none |
| Arbitrary value | shadow-[...] |
| Custom inset | shadow-[inset_...] |
Key takeaways:
- Box shadows follow the border box; drop shadows follow the rendered content. Use
shadow-*for cards, buttons, and modals. Usedrop-shadow-*for text, SVG icons, and images with transparency. - The default scale provides six elevation levels.
shadow-smthroughshadow-2xlcover the range from subtle lift to dramatic emphasis. The intermediate levels use multiple shadow layers for a more natural falloff . - Inset shadows simulate recession.
shadow-inneris the default inset shadow, useful for inputs and wells. Custom inset shadows require theinsetkeyword at the start of an arbitrary value . - Shadow colors are independent of shadow geometry. Tailwind v4.1 added
shadow-{color}anddrop-shadow-{color}utilities, allowing shadows to be tinted with any theme color and opacity modifier . - Transition shadow changes for smooth interaction.
transition-shadowanimates the shadow over 150ms, which is usually enough for hover and focus effects . - Arbitrary values handle one-off shadows. The
shadow-[...]syntax generates a custom box-shadow on the fly. Underscores become spaces in the output. - Drop shadows are more expensive than box shadows. The browser must compute the alpha channel of the element’s rendered content. For large lists of rectangular elements, box shadows are the better choice.
Remember: Shadows communicate depth, and depth communicates hierarchy. Box shadows are the workhorse: they follow rectangles, render efficiently, and cover most elevation needs. Drop shadows are the specialist: they follow the actual shape of text and transparent images, producing results that box shadows cannot. Inset shadows are the counterpoint: they press an element into the surface rather than lifting it above. Tailwind’s shadow scale gives you a consistent set of elevation levels, and v4.1’s color utilities let you tint any shadow to match your design system. Choose the mechanism that matches the shape, use the scale that matches the elevation, and transition the change so the interface feels alive.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!