If you have ever seen a heading with a soft glow behind it, or letters that look like they are lifted off the page with a hard offset, that is CSS text shadow doing its job. It looks like a complex property when you first encounter it, but once you understand what each value controls, it becomes one of the easiest ways to add depth and personality to your typography.

This guide covers the full syntax, what each value does, how to stack multiple shadows, and a set of ready-to-use patterns for the effects you will actually need.

What is CSS text-shadow?

The text-shadow property adds one or more shadows directly behind the characters in a text element. You control where the shadow sits, how blurry it is, and what color it should be. That is the entire model.

It has been supported in all major browsers for many years. No vendor prefixes, no polyfills, no fallbacks needed. It works in Chrome, Firefox, Safari, Edge, and on every major mobile browser without any extra setup.

The syntax

The full syntax for a single shadow is:

text-shadow: offset-x offset-y blur-radius color;

Each value has a specific role:

  • offset-x — How far the shadow moves horizontally. Positive moves it right, negative moves it left.
  • offset-y — How far the shadow moves vertically. Positive moves it down, negative moves it up.
  • blur-radius — How blurry the shadow is. A value of 0 gives a hard edge. Higher values spread the shadow out and soften it. This value is optional and defaults to 0 if omitted.
  • color — The color of the shadow. Accepts any valid CSS color format: hex, rgb, rgba, hsl. Technically optional, but always set it explicitly to avoid inconsistent browser defaults.

A basic example

Here is the most common use case — a soft drop shadow on a heading:

h1 {
  text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.4);
}

Reading that: the shadow is 2px to the right, 2px down, blurred by 4px, and is semi-transparent black. This is the pattern you will use most often for headings on light or medium backgrounds.

What each value does to the result

Changing the offset

A small offset creates subtle depth. A large offset creates a bold, graphic shadow. Zero offset with only blur creates a centered glow with no directional light source.

/* Subtle depth */
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.3);

/* Bold retro offset */
text-shadow: 5px 5px 0px #000;

/* Centered glow — no directional offset */
text-shadow: 0px 0px 12px rgba(124, 106, 247, 0.9);

Changing the blur radius

Zero blur gives a hard, sharp-edged shadow. This works well for retro and graphic styles. Higher blur values produce soft glows. Use these for neon effects or atmospheric display headings.

/* Hard edge — zero blur */
text-shadow: 3px 3px 0 #222;

/* Soft atmospheric glow */
text-shadow: 0 0 20px rgba(124, 106, 247, 0.8);

Using rgba instead of solid colors

Using rgba lets you control how strong the shadow appears through the alpha channel. Semi-transparent shadows almost always look more natural than solid black or solid color shadows, which can feel flat and dated.

/* Harsh — avoid this for body text */
text-shadow: 2px 2px 4px #000000;

/* Natural — prefer this */
text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.35);

Multiple text shadows

You can stack multiple shadows on a single element by separating them with commas. Each shadow is rendered independently and layered in the order they are written, with the first one on top.

h1 {
  text-shadow:
    1px 1px 0 #ccc,
    2px 2px 0 #bbb,
    3px 3px 0 #aaa,
    4px 4px 0 #999;
}

That example builds a 3D stacked effect by placing four offset shadows in progressively darker shades. Each one sits one pixel further than the last, creating the illusion of depth and volume.

Note: There is no limit to how many shadows you can stack. The cost is that each additional shadow adds rendering work. For most effects, two to four shadows is enough.

All values at a glance

ValueRequiredWhat it controls
offset-xYesHorizontal position of the shadow
offset-yYesVertical position of the shadow
blur-radiusNo (default: 0)How soft and spread out the shadow is
colorNo (recommended)The color of the shadow

Practical CSS text shadow examples

Classic drop shadow

h2 {
  text-shadow: 2px 3px 6px rgba(0, 0, 0, 0.3);
}

Solid choice for headings on light backgrounds. Adds depth without drawing attention to itself.

Neon glow effect

h1 {
  color: #fff;
  text-shadow:
    0 0 7px #fff,
    0 0 10px #fff,
    0 0 21px #fff,
    0 0 42px #7c6af7,
    0 0 82px #7c6af7;
}

Stack multiple centered shadows with increasing blur radii. Works best on dark backgrounds. The white inner glow creates the bright core, and the colored outer glows create the neon bleed effect.

Hard retro shadow

h1 {
  color: #fff;
  text-shadow: 4px 4px 0px #222;
}

Zero blur, solid offset. Bold and graphic. Works best with thick display fonts and high-contrast backgrounds. This is the retro poster look.

3D stacked shadow

h1 {
  color: #e2e8f0;
  text-shadow:
    1px 1px 0 #555,
    2px 2px 0 #444,
    3px 3px 0 #333,
    4px 4px 0 #222,
    5px 5px 0 #111;
}

Each layer adds one more pixel of offset and slightly deeper color. Gives the impression that the letters are extruded off the page.

Embossed text

p {
  color: #94a3b8;
  text-shadow: 1px 1px 1px #fff, -1px -1px 1px #444;
}

Two opposing shadows — one light, one dark. The combination makes the text look raised out of the surface like a physical emboss stamp.

Engraved text

p {
  color: #94a3b8;
  text-shadow: -1px -1px 1px #fff, 1px 1px 1px #444;
}

Same two shadows but reversed. The light source appears to come from the opposite direction, making the text look carved into the surface instead of raised above it.

Legibility shadow for text over images

p {
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.6);
}

This is a practical pattern, not a decorative one. When white text sits over a photo or gradient background, a subtle shadow underneath ensures the text stays readable as the background changes behind it.

text-shadow vs filter: drop-shadow()

These two produce similar results on text but they are not the same property.

PropertyApplies toPerformanceUse for
text-shadowText characters only✅ LighterText styling
filter: drop-shadow()Entire element including transparent areas🟡 HeavierImages, SVGs, icons

For text, always use text-shadow. It is the right tool. filter: drop-shadow() is better suited to images, SVGs, and PNG icons where you want the shadow to follow the visible shape of the element rather than its bounding box.

Performance considerations

A single text-shadow has almost no performance cost. Where things get expensive:

  • Stacking many shadows on many elements at once
  • Using very large blur radius values
  • Animating text-shadow directly with CSS transitions or keyframes

Do not animate text-shadow directly. It triggers repaint on every frame. If you need an animated glow or shadow, animate the opacity of a pseudo-element with a fixed shadow instead. That uses GPU compositing and stays smooth.

Common mistakes to avoid

  • Heavy blur on body text — High blur reduces legibility. Keep blur low for text people need to read. Save large blur values for display headings or decorative elements.
  • Pure black without transparency — Solid black shadows look harsh. Use rgba(0, 0, 0, 0.3) style values instead.
  • Applying it everywhere — Text shadow works best when it is intentional. Using it on every element makes a page feel cluttered and visually noisy.
  • Large offsets on small text — A 5px offset works on a 60px heading. On 14px body text it looks broken. Scale your shadow values relative to the font size.

Browser support

Full support across all modern browsers. Chrome, Firefox, Safari, Edge, Opera, and all major mobile browsers support text-shadow without vendor prefixes. You can use it in production today without any compatibility concerns.

Tip: The color value can be written before or after the offset and blur values. Both are valid CSS. For consistency, pick one order and stick to it across your codebase. Most developers write color last.

FAQ

Can you add multiple shadows to text in CSS?

Yes. Separate each shadow definition with a comma and they will all apply to the same element. Each shadow is rendered independently and layered in the order they appear in your CSS.

Is blur-radius required?

No. You can write text-shadow: 3px 3px #000; and it is valid. Omitting blur-radius defaults it to zero, which gives a sharp hard-edged shadow with no softness.

Does text-shadow work on inline elements?

Yes. It works on any element that renders text, including span, a, strong, em, and all heading and paragraph elements.

Can text-shadow be animated?

CSS technically supports animating text-shadow with transitions and keyframes, but it is expensive. Each frame triggers a repaint. If you need motion on a shadow, animate the opacity of a pseudo-element with a fixed shadow instead.

What is the difference between text-shadow and filter: drop-shadow()?

text-shadow applies to the text characters only. filter: drop-shadow() applies to the entire rendered element including transparent areas. For text, use text-shadow. For images and SVGs, filter: drop-shadow() is more appropriate.

Build text shadows visually

Our CSS Text Shadow Generator lets you adjust offset, blur, and color in real time and copy the generated CSS directly into your project.

Open Text Shadow Generator →