Skip to content
HexSlate

CSS Text Shadow Generator

Shadow work

Passes the AA thresholdsThe shadow leaves 9.72:1 of contrast at the glyph edge. The text on the background alone is 16.62:1.
CSS
.headline {
  text-shadow:
    0 1px 0 rgb(11 28 30 / 0.25),
    0 2px 4px rgb(11 28 30 / 0.2),
    0 8px 16px rgb(11 28 30 / 0.15);
}
Tailwind v4.1+
text-shadow-[0_1px_0_rgb(11_28_30_/_0.25),_0_2px_4px_rgb(11_28_30_/_0.2),_0_8px_16px_rgb(11_28_30_/_0.15)]
3 layers56px92 characters of CSS

A text shadow is the same layer list a box shadow is, minus spread and inset. Neon, outline, letterpress and retro 3D are all that shorter grammar used several times over.

How each preset is built

Neon is one colour blurred at four widths with all offsets at zero, which is what separates a glow from a shadow. Retro 3D and Long shadow are 1px steps down the diagonal, one layer per step, every step fully opaque: translucent steps overlap and band instead of blending. Emboss is one light layer 1px below and one dark 1px above, so it needs a mid-tone background with room for both.

Outline is four hard 1px offsets at the diagonals, and its tell is square corners where a real stroke would round them. Use -webkit-text-stroke with paint-order: stroke fill instead, so the stroke paints behind the fill rather than eating half the letter from inside.

The contrast trap

A shadow changes what your text is read against. Contrast is normally text against background, but a shadow paints a halo at the edge of every glyph, and that halo is what the letterform separates from. A cyan glow behind white text on black leaves page contrast near 20:1 while the glyph edge sits below 2:1.

The check composites each layer over the background at its own alpha and measures the text against the result. WCAG 2.2 asks for 4.5:1 for normal text and 3:1 for large, meaning 18pt (24px) or 14pt bold. WCAG has no rule for shadows though, so this is an interpretation rather than a conformance verdict, and it warns early: a heavily blurred layer never reaches full alpha in practice, so a wide soft glow measures denser here than it renders. Offsets stay out of the measurement as well, so a layer thrown well clear of the letter is still the one named when the check points at a layer.

Common problems

  • The effect disappears at body size. Offsets are absolute lengths, so a 4px offset that reads as depth on a 64px headline is a smear on 16px body copy. Scale the offsets with the type, or keep the effect on headings.
  • A snippet from elsewhere has no colour. The colour is optional; without it browsers paint in currentColor, so the shadow tracks the text colour.
  • The shadow ended up on top of the letter. Layers paint front to back in written order. In a stepped 3D effect the steps run outward from the glyph, nearest first.

Frequently asked questions

Why does text-shadow have no spread when box-shadow does?

A box is a rectangle whose outline is trivial to expand. A glyph outline is not: growing it correctly is what a font stroke does, and it costs far more. So the property takes three lengths, not four, and has no inset either.

Can I use this for an outline instead of a stroke?

At 1px, yes. Past about 2px the four-offset trick shows gaps at the diagonals and needs eight or more layers to close them, where -webkit-text-stroke is cheaper and correct.

Does the Tailwind class work in every Tailwind v4 version?

text-shadow-* arrived in v4.1. On anything earlier use the arbitrary-property form, which has worked since v3.1. Underscores stand in for spaces in both.

Does a text shadow hurt readability?

It can, badly, and that is why this page measures it. A shadow paints a halo immediately around each glyph, so the letter edge is read against the halo rather than against the page. A heavy glow can drop effective contrast below the WCAG AA thresholds while the text still looks fine to whoever added it.