Tailwind CSS Handbook v4.3

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#

UtilityElevation
shadow-2xsBarely there
shadow-xsHairline
shadow-smCards at rest
shadow-mdRaised
shadow-lgDropdowns, popovers
shadow-xlModals
shadow-2xlHero elements
shadow-noneRemove
Loading preview…

The same one-step shift applies to drop-shadow-*, blur-* and backdrop-blur-*.

Coloured shadows#

HTML
<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#

HTML
<div class="inset-shadow-sm inset-shadow-gray-900/10 rounded-lg bg-gray-100 p-4">…</div>

Useful for pressed states and wells:

HTML
<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.

UtilitySize
drop-shadow-xs drop-shadow-sm drop-shadow-md drop-shadow-lg drop-shadow-xl drop-shadow-2xlPresets
drop-shadow-cyan-500/50Coloured v4.1
Loading preview…

Text shadow#

v4.1

UtilitySize
text-shadow-2xs text-shadow-xs text-shadow-sm text-shadow-md text-shadow-lgPresets
text-shadow-indigo-500/30Coloured
text-shadow-noneRemove

Its main job is keeping text legible over photography — see Text Styling.

Shadows vs rings#

shadow-*ring-*
LookSoft, directionalCrisp, uniform
SuggestsHeight above the surfaceA boundary or focus
Visible on dark backgroundsPoorlyWell
Right forCards, modals, dropdownsFocus states, subtle separation

Combining both is idiomatic for cards:

HTML
<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:

app.css
@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);
}
HTML
<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#

Loading preview…

The combination of a tiny -translate-y and a larger shadow is what sells the lift. Either alone feels flat.

Layered dropdown#

HTML
<div class="rounded-lg bg-white py-1 shadow-lg ring-1 ring-black/5">…</div>

Sticky header that gains a shadow on scroll#

HTML
<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-sm is 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-2xl on a badge looks like a bug.
  • shadow-* on a transparent PNG. It shadows the rectangle. Use drop-shadow-*.
  • Animating box-shadow on many elements. It is not GPU-accelerated; prefer animating opacity on a pseudo-element for heavy cases. See Transitions.