Shadows
Box shadows, inset shadows, drop shadows and text shadows — with the v4 size rename and how to build a coherent elevation system.
Shadows communicate elevation. Tailwind gives you four kinds, and v4 renamed the size scale.
Box shadow#
| Utility | Elevation |
|---|---|
shadow-2xs | Barely there |
shadow-xs | Hairline |
shadow-sm | Cards at rest |
shadow-md | Raised |
shadow-lg | Dropdowns, popovers |
shadow-xl | Modals |
shadow-2xl | Hero elements |
shadow-none | Remove |
<div class="grid grid-cols-2 gap-4 bg-gray-50 p-6 text-xs sm:grid-cols-4">
<div class="rounded-lg bg-white p-4 text-center shadow-xs">xs</div>
<div class="rounded-lg bg-white p-4 text-center shadow-sm">sm</div>
<div class="rounded-lg bg-white p-4 text-center shadow-lg">lg</div>
<div class="rounded-lg bg-white p-4 text-center shadow-2xl">2xl</div>
</div>The same one-step shift applies to drop-shadow-*, blur-* and backdrop-blur-*.
Coloured shadows#
<div class="shadow-lg shadow-indigo-500/40">…</div>
<button class="shadow-md shadow-emerald-600/30 hover:shadow-lg hover:shadow-emerald-600/40">…</button>A shadow tinted with the element's own colour reads as a glow and works well for primary buttons. Keep the opacity low — 20–40% — or it looks like a smudge.
Inset shadows#
<div class="inset-shadow-sm inset-shadow-gray-900/10 rounded-lg bg-gray-100 p-4">…</div>Useful for pressed states and wells:
<button class="rounded-md bg-gray-100 px-4 py-2 active:inset-shadow-sm">Press me</button>Drop shadow#
drop-shadow-* is a filter, so it follows the shape of the content rather than the box — the right choice for PNGs with transparency and for SVG icons.
| Utility | Size |
|---|---|
drop-shadow-xs drop-shadow-sm drop-shadow-md drop-shadow-lg drop-shadow-xl drop-shadow-2xl | Presets |
drop-shadow-cyan-500/50 | Coloured v4.1 |
<div class="flex items-center gap-6 bg-gray-50 p-6">
<div class="size-16 bg-indigo-500 shadow-lg" style="clip-path: polygon(50% 0, 100% 100%, 0 100%)"></div>
<div class="size-16 bg-emerald-500 drop-shadow-lg" style="clip-path: polygon(50% 0, 100% 100%, 0 100%)"></div>
<p class="text-xs text-gray-600">Left: <code>shadow-lg</code> follows the box.<br>Right: <code>drop-shadow-lg</code> follows the shape.</p>
</div>Text shadow#
v4.1
| Utility | Size |
|---|---|
text-shadow-2xs text-shadow-xs text-shadow-sm text-shadow-md text-shadow-lg | Presets |
text-shadow-indigo-500/30 | Coloured |
text-shadow-none | Remove |
Its main job is keeping text legible over photography — see Text Styling.
Shadows vs rings#
shadow-* | ring-* | |
|---|---|---|
| Look | Soft, directional | Crisp, uniform |
| Suggests | Height above the surface | A boundary or focus |
| Visible on dark backgrounds | Poorly | Well |
| Right for | Cards, modals, dropdowns | Focus states, subtle separation |
Combining both is idiomatic for cards:
<div class="rounded-xl bg-white p-6 shadow-lg ring-1 ring-gray-900/5">…</div>The ring provides a crisp edge; the shadow provides depth.
Shadows in dark mode#
Building an elevation system#
Rather than picking shadows ad hoc, name the levels:
@theme {
--shadow-raised: 0 1px 2px 0 oklch(0 0 0 / 0.05);
--shadow-overlay: 0 10px 24px -8px oklch(0 0 0 / 0.18), 0 2px 6px -2px oklch(0 0 0 / 0.08);
--shadow-modal: 0 24px 56px -12px oklch(0 0 0 / 0.28);
}<div class="shadow-raised">Card</div>
<div class="shadow-overlay">Dropdown</div>
<div class="shadow-modal">Dialog</div>Now elevation is a vocabulary, not a set of magic numbers, and it can be tuned in one place.
Common patterns#
Card that lifts on hover#
<div class="bg-gray-50 p-6">
<a href="#" class="block max-w-sm rounded-xl bg-white p-5 shadow-sm ring-1 ring-gray-900/5 transition duration-200 hover:-translate-y-0.5 hover:shadow-lg">
<h3 class="font-semibold text-gray-900">Hover me</h3>
<p class="mt-1 text-sm text-gray-600">A small lift plus a deeper shadow reads as "interactive".</p>
</a>
</div>The combination of a tiny -translate-y and a larger shadow is what sells the lift. Either alone feels flat.
Layered dropdown#
<div class="rounded-lg bg-white py-1 shadow-lg ring-1 ring-black/5">…</div>Sticky header that gains a shadow on scroll#
<header class="sticky top-0 z-40 bg-white/85 backdrop-blur transition-shadow data-[scrolled=true]:shadow-sm">…</header>Common mistakes#
- Using v3 shadow names.
shadow-smis now much lighter; check your cards after upgrading. - Too many elevation levels. Three or four is plenty. More and nothing reads as meaningfully raised.
- Shadows on dark backgrounds. Use rings instead.
- Heavy shadows on small elements.
shadow-2xlon a badge looks like a bug. shadow-*on a transparent PNG. It shadows the rectangle. Usedrop-shadow-*.- Animating
box-shadowon many elements. It is not GPU-accelerated; prefer animatingopacityon a pseudo-element for heavy cases. See Transitions.
Related topics#
- Borders — rings and outlines
- Colors — tinting shadows
- Filters & Effects —
drop-shadowas part of the filter chain - Dark Mode — elevation in dark themes