What is CSS text-shadow

text-shadow adds one or more shadows to the glyphs of text (letters). It’s like box-shadow, but for text. It can be subtle (a gentle lift) or dramatic (neon sign energy).

Two important notes right away:

  • Text shadow is not layout: it doesn’t affect spacing, line-height, or element size. It’s paint-only.
  • Text shadow is not “inset”: unlike box-shadow, there is no inset keyword. We’ll cover alternatives later.
.demo-title {
  text-shadow: 0 2px 10px rgba(255, 255, 255, 0.35);
}
  
.demo-title {
  text-shadow: 3px 3px 0 rgba(0, 0, 0, 0.65);
}
  
.demo-title {
  text-shadow: 0 0 18px rgba(0, 200, 255, 0.85);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 28px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #0f1220;
}

.demo-title {
  margin: 0;
  font: 800 56px/1.05 system-ui, ui-sans-serif, sans-serif;
  letter-spacing: 0.02em;
  color: #f6f7ff;
}

.demo-sub {
  margin: 10px 0 0;
  font: 500 16px/1.5 system-ui, ui-sans-serif, sans-serif;
  color: rgba(246, 247, 255, 0.8);
}
  

Text Shadow

Click the snippets to compare subtle lift, hard shadow, and glow.

CSS text-shadow property and syntax

The basic syntax is:

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

  • offset-x: horizontal distance. Positive goes right, negative goes left.
  • offset-y: vertical distance. Positive goes down, negative goes up.
  • blur-radius (optional): how soft the shadow is. Bigger = blurrier.
  • color (optional): the shadow color. If omitted, it uses the current text color (which can be surprising).

You can also provide multiple shadows separated by commas: text-shadow: shadow1, shadow2, shadow3;

.demo-title {
  text-shadow: 8px 10px 18px rgba(255, 255, 255, 0.45);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: linear-gradient(180deg, #151a2a, #0d1020);
}

.demo-title {
  margin: 0;
  font: 900 60px/1.05 system-ui, ui-sans-serif, sans-serif;
  letter-spacing: 0.02em;
  color: #f6f7ff;
}

.hint {
  margin: 10px 0 0;
  font: 500 14px/1.5 system-ui, ui-sans-serif, sans-serif;
  color: rgba(246, 247, 255, 0.75);
}
  

Drag Me

Use the sliders to understand x, y, and blur.

CSS text-shadow examples

People usually learn fastest with “copy, paste, tweak.” Here are a few common patterns:

  • Subtle lift: small offsets, medium blur, low opacity.
  • Hard shadow: bigger offsets, blur = 0.
  • Glow: offsets = 0, blur high, bright color.
  • Depth stack: multiple comma-separated shadows.
.demo-title {
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.3);
}
  
.demo-title {
  text-shadow: 6px 6px 0 rgba(0, 0, 0, 0.6);
}
  
.demo-title {
  text-shadow:
    0 0 10px rgba(255, 90, 240, 0.75),
    0 0 24px rgba(255, 90, 240, 0.55);
}
  
.demo-title {
  text-shadow:
    0 2px 0 rgba(0, 0, 0, 0.55),
    0 6px 18px rgba(0, 0, 0, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 26px 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #999;
}

.demo-title {
  margin: 0;
  font: 900 58px/1.05 system-ui, ui-sans-serif, sans-serif;
  color: #f7f7ff;
}

.demo-sub {
  margin: 10px 0 0;
  font: 500 15px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(247, 247, 255, 0.78);
}
  

Examples

Try each snippet: lift, hard shadow, glow, and depth stack.

CSS text-shadow blur

The blur radius makes the shadow softer. A blur of 0 means the shadow edge is crisp (pixel-sharp). A blur of 20px spreads the shadow out and fades it.

Blur does not “move” the shadow. Movement comes from the x/y offsets.

.demo-title {
  text-shadow: 10px 10px 0 rgba(255, 255, 255, 0.55);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 28px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #14192b;
}

.demo-title {
  margin: 0;
  font: 900 64px/1 system-ui, ui-sans-serif, sans-serif;
  color: #ffffff;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.5 system-ui, ui-sans-serif, sans-serif;
  color: rgba(255, 255, 255, 0.78);
}
  

Blur Me

Same x/y offsets, only blur changes. Crisp to cloudy.

CSS text-shadow opacity

Opacity is usually controlled through the shadow color. The most common approach is rgba():

  • rgba(0, 0, 0, 0.25) is a gentle shadow.
  • rgba(0, 0, 0, 0.85) is a heavy shadow.

You can also use hsl() with alpha: hsl(210 100% 60% / 0.6).

Tip: if you use a fully opaque color like #000 with a big blur radius, the shadow can look muddy. Lowering alpha usually looks more professional.

        
.demo-title {
  --a: 0.35;
  text-shadow: 0 10px 24px rgba(0, 0, 0, var(--a));
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: linear-gradient(180deg, #f2f6ff, #dfe7ff);
}

.demo-title {
  margin: 0;
  font: 900 62px/1 system-ui, ui-sans-serif, sans-serif;
  letter-spacing: 0.01em;
  color: #121529;
}

.hint {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(18, 21, 41, 0.72);
}
  

Opacity

Slide alpha from invisible to dramatic.

CSS text shadow inset

Let’s clear up a super common confusion: There is no inset keyword for text-shadow. If you try it, the declaration becomes invalid (the browser will ignore it).

If your goal is an “inner shadow” look inside the text, you have a few practical options:

  • Use a highlight instead: a negative y offset with blur can suggest “inner depth.”
  • Use multiple shadows to fake a carved look.
  • For truly advanced effects, use background-clip: text and layer pseudo-elements (more on layering later).
.demo-title {
  text-shadow:
    0 2px 0 rgba(0, 0, 0, 0.55),
    0 -2px 0 rgba(255, 255, 255, 0.18);
}
  
.demo-title {
  text-shadow:
    0 1px 0 rgba(255, 255, 255, 0.2),
    0 10px 22px rgba(0, 0, 0, 0.45);
}
  
.demo-title {
  text-shadow:
    0 -2px 10px rgba(255, 255, 255, 0.14),
    0 10px 22px rgba(0, 0, 0, 0.6);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #1a1f33;
}

.demo-title {
  margin: 0;
  font: 900 62px/1 system-ui, ui-sans-serif, sans-serif;
  color: #f6f7ff;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(246, 247, 255, 0.76);
}
  

“Inset”

No inset keyword, but you can fake depth with stacked highlights and shadows.

CSS text shadow effects

Once you’re comfortable with syntax, the fun part is stacking shadows to create styles. Think of each shadow as a layer of paint.

Long shadow effect

The “long shadow” is basically lots of crisp shadows, each offset by 1px more than the last. In real projects, you might generate these with a preprocessor, but it’s helpful to see the idea.

.demo-title {
  text-shadow:
    1px 1px 0 rgba(0, 0, 0, 0.35),
    2px 2px 0 rgba(0, 0, 0, 0.35),
    3px 3px 0 rgba(0, 0, 0, 0.35),
    4px 4px 0 rgba(0, 0, 0, 0.35),
    5px 5px 0 rgba(0, 0, 0, 0.35),
    6px 6px 0 rgba(0,  0, 0, 0.35),
    7px 7px 0 rgba(0, 0, 0, 0.35),
    8px 8px 0 rgba(0, 0, 0, 0.35),
    9px 9px 0 rgba(0, 0, 0, 0.35),
    10px 10px 0 rgba(0, 0, 0, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #ffe4a6;
}

.demo-title {
  margin: 0;
  font: 900 64px/1 system-ui, ui-sans-serif, sans-serif;
  color: #1a1a1a;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(26, 26, 26, 0.75);
}
  

Long Shadow

Crisp, repeated shadows create a flat “poster” depth.

Neon glow effect

Glows are usually zero offsets and multiple blurs. Stacking a few gives a richer glow than a single blur.

.demo-title {
  text-shadow:
    0 0 8px rgba(120, 255, 210, 0.75),
    0 0 18px rgba(120, 255, 210, 0.55),
    0 0 36px rgba(120, 255, 210, 0.35);
}
  
.demo-title {
  text-shadow:
    0 0 6px rgba(255, 120, 230, 0.75),
    0 0 16px rgba(255, 120, 230, 0.55),
    0 0 34px rgba(255, 120, 230, 0.38);
}
  
.demo-title {
  text-shadow:
    0 0 3px rgba(255, 255, 255, 0.65),
    0 0 14px rgba(0, 190, 255, 0.6),
    0 0 34px rgba(0, 190, 255, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #060714;
}

.demo-title {
  margin: 0;
  font: 900 62px/1 system-ui, ui-sans-serif, sans-serif;
  letter-spacing: 0.02em;
  color: #f6f7ff;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(246, 247, 255, 0.75);
}
  

Neon

Multiple blurred layers look more “real” than one giant blur.

CSS text shadow outline

A classic trick: create an “outline” by stacking text shadows around the text in several directions. This works everywhere, because it’s just multiple shadows.

The simplest outline uses 4 directions (left, right, up, down). A nicer outline uses 8 directions (add diagonals).

.demo-title {
  text-shadow:
    2px 0 0 #111,
    -2px 0 0 #111,
    0 2px 0 #111,
    0 -2px 0 #111;
}
  
.demo-title {
  text-shadow:
    2px 0 0 #111,
    -2px 0 0 #111,
    0 2px 0 #111,
    0 -2px 0 #111,
    2px 2px 0 #111,
    -2px -2px 0 #111,
    2px -2px 0 #111,
    -2px 2px 0 #111;
}
  
.demo-title {
  text-shadow:
    2px 0 0 rgba(0, 0, 0, 0.7),
    -2px 0 0 rgba(0, 0, 0, 0.7),
    0 2px 0 rgba(0, 0, 0, 0.7),
    0 -2px 0 rgba(0, 0, 0, 0.7),
    0 10px 22px rgba(0, 0, 0, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #ffd8ea;
}

.demo-title {
  margin: 0;
  font: 900 66px/1 system-ui, ui-sans-serif, sans-serif;
  color: #ffffff;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(17, 17, 17, 0.76);
}
  

Outline

Try 4-direction vs 8-direction outline, then add a drop shadow for depth.

Outline vs -webkit-text-stroke

There’s also -webkit-text-stroke, which can create a clean outline in supporting browsers. It’s not the same as text-shadow, but it’s a useful comparison.

.demo-title {
  -webkit-text-stroke: 3px #111;
  text-shadow: 0 12px 22px rgba(0, 0, 0, 0.35);
}
  
.demo-title {
  text-shadow:
    2px 0 0 #111,
    -2px 0 0 #111,
    0 2px 0 #111,
    0 -2px 0 #111,
    2px 2px 0 #111,
    -2px -2px 0 #111,
    2px -2px 0 #111,
    -2px 2px 0 #111,
    0 12px 22px rgba(0, 0, 0, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #b7f0ff;
}

.demo-title {
  margin: 0;
  font: 900 66px/1 sans-serif, arial;
  color: #ffffff;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(17, 17, 17, 0.76);
}
  

Stroke

First snippet uses text-stroke. Second uses the multi-shadow outline trick.

Learn more about text stroke in the CSS Text Outline Interactive Tutorial.

CSS text shadow gradient

Here’s the honest truth: text-shadow cannot be a gradient. The shadow color is a single color per shadow layer.

But you can still get “gradient-ish” results with smart workarounds:

  • Make the text itself a gradient, then add a normal shadow.
  • Use multiple shadows with different colors to fake a gradient glow.
  • Layer a blurred duplicate of the text behind the main text (using ::before).

Gradient text plus text-shadow

This gives you gradient letters with a regular shadow. It’s often what people actually want.

.demo-title {
  background: linear-gradient(90deg, #ff4bd8, #5ce7ff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 10px 22px rgba(0, 0, 0, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #0b0d18;
}

.demo-title {
  margin: 0;
  font: 900 66px/1 system-ui, ui-sans-serif, sans-serif;
  letter-spacing: 0.01em;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(246, 247, 255, 0.78);
}
  

Gradient

The gradient is on the text fill, the shadow is still a normal color.

Fake a gradient glow with multiple shadows

You can approximate a gradient by stacking shadows with different colors and blur values. It’s not a true gradient, but it looks cool and it’s pure CSS.

.demo-title {
  text-shadow:
    0 0 10px rgba(255, 75, 216, 0.55),
    0 0 22px rgba(92, 231, 255, 0.45),
    0 0 44px rgba(92, 231, 255, 0.28);
}
  
.demo-title {
  text-shadow:
    -6px 0 16px rgba(255, 75, 216, 0.45),
    6px 0 16px rgba(92, 231, 255, 0.45),
    0 0 44px rgba(255, 255, 255, 0.18);
}
  
.demo-title {
  text-shadow:
    0 0 8px rgba(255, 255, 255, 0.2),
    0 0 18px rgba(255, 75, 216, 0.45),
    0 0 36px rgba(92, 231, 255, 0.35);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.stage {
  padding: 30px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #070814;
}

.demo-title {
  margin: 0;
  font: 900 64px/1 system-ui, ui-sans-serif, sans-serif;
  color: #f6f7ff;
  letter-spacing: 0.02em;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(246, 247, 255, 0.75);
}
  

Glow Stack

Multiple colors can “feel” like a gradient, even if it’s layers.

Common mistakes and debugging

  • Nothing happens: check spelling (text-shadow), and make sure your selector matches the element.
  • Shadow looks blurry and ugly: reduce blur, reduce opacity, or avoid pure black at high blur.
  • Shadow is cut off: text shadows can get clipped if an ancestor has overflow: hidden.
  • Unreadable text: outlines and glows are fun, but keep contrast high for real content.
  • Performance: lots of shadows on lots of text can be expensive. Use fancy effects for headings, not entire paragraphs.
.card {
  overflow: hidden;
}

.demo-title {
text-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
} 
.card {
  overflow: visible;
}

.demo-title {
  text-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
}
  
.card {
  overflow: hidden;
  padding: 60px 28px;
}

.demo-title {
  text-shadow: 0 18px 40px rgba(0, 0, 0, 0.55);
}
  
*,
::before,
::after {
  box-sizing: border-box;
}

.card {
  padding: 28px;
  border: 3px solid #111;
  border-radius: 14px;
  background: #eef2ff;
}

.demo-title {
  margin: 0;
  font: 900 64px/1 system-ui, ui-sans-serif, sans-serif;
  color: #121529;
}

.note {
  margin: 10px 0 0;
  font: 500 14px/1.6 system-ui, ui-sans-serif, sans-serif;
  color: rgba(18, 21, 41, 0.7);
}
  

Clipping

Try each snippet: overflow hidden clips shadows unless you add enough padding (or make overflow visible).

Quick cheat sheet

  • text-shadow: 0 2px 10px rgba(0,0,0,0.3); is a great default “lift.”
  • text-shadow: 6px 6px 0 rgba(0,0,0,0.6); is a comic-style hard shadow.
  • text-shadow: 0 0 20px rgba(0,200,255,0.7); is instant glow.
  • For outlines, stack 4 to 8 shadows around the text.
  • No inset keyword. If you see “text-shadow inset” in the wild, it’s either a mistake or a different technique.
  • No gradient shadow directly. Fake it with multiple colored shadows or use gradient text with a normal shadow.

CSS Text Shadow Conclusion

The text-shadow property is a powerful tool for adding depth and style to your text. With a solid understanding of its syntax and some creative experimentation, you can achieve a wide range of effects, from subtle lifts to dramatic glows. Remember to keep performance in mind when using multiple shadows, and always test your designs across different browsers to ensure compatibility. Happy styling!

Learn more about shadows in CSS in the CSS Shadow Interactive Tutorial.