25 CSS Text Animations 04 / 25
CSS Neon Glow Text Animation
Layered multi-colour text-shadow stacks create a pulsing neon sign effect with realistic flicker and electric glow spread.
The code
<div class="ta-04">
<div class="ta-04__stage">
<p class="ta-04__label">Open</p>
<h2 class="ta-04__sign">
<span class="ta-04__s1">N</span><span class="ta-04__s2">E</span><span
class="ta-04__s3">O</span><span class="ta-04__s4">N</span>
</h2>
<p class="ta-04__sub">text-shadow stacking · flicker keyframes</p>
</div>
</div> <div class="ta-04">
<div class="ta-04__stage">
<p class="ta-04__label">Open</p>
<h2 class="ta-04__sign">
<span class="ta-04__s1">N</span><span class="ta-04__s2">E</span><span
class="ta-04__s3">O</span><span class="ta-04__s4">N</span>
</h2>
<p class="ta-04__sub">text-shadow stacking · flicker keyframes</p>
</div>
</div>.ta-04, .ta-04 *, .ta-04 *::before, .ta-04 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-04 ::selection { background: #fb7185; color: #fff; }
.ta-04 {
--bg: #030309;
--pink: #ff2d78;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', sans-serif;
}
.ta-04__stage { text-align: center; }
.ta-04__label {
font-size: 0.7rem;
letter-spacing: 0.4em;
text-transform: uppercase;
color: #ff2d78;
text-shadow:
0 0 4px #ff2d78,
0 0 12px #ff2d78;
margin-bottom: 0.5rem;
}
.ta-04__sign {
font-size: clamp(4rem, 12vw, 7rem);
font-weight: 900;
letter-spacing: 0.1em;
color: #fff;
display: flex;
gap: 0.05em;
}
.ta-04__sign span {
display: inline-block;
text-shadow:
0 0 5px #fff,
0 0 10px #fff,
0 0 20px var(--pink),
0 0 40px var(--pink),
0 0 80px var(--pink),
0 0 90px var(--pink);
}
.ta-04__s1 { animation: ta-04-flicker1 4.5s infinite; }
.ta-04__s2 { animation: ta-04-flicker2 3.8s infinite; color: #ff8fab; text-shadow:
0 0 5px #fff, 0 0 10px #fff, 0 0 20px #ff8fab, 0 0 40px #ff8fab, 0 0 80px #ff8fab; }
.ta-04__s3 { animation: ta-04-flicker1 5.2s 0.6s infinite; }
.ta-04__s4 { animation: ta-04-flicker2 4.1s 1.2s infinite; }
.ta-04__sub {
font-size: 0.68rem;
color: #2d1f2a;
margin-top: 1.2rem;
letter-spacing: 0.1em;
font-family: 'Courier New', monospace;
}
@keyframes ta-04-flicker1 {
0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% {
opacity: 1;
text-shadow:
0 0 5px #fff, 0 0 10px #fff,
0 0 20px var(--pink), 0 0 40px var(--pink),
0 0 80px var(--pink), 0 0 90px var(--pink);
}
20%, 24%, 55% {
opacity: 0.4;
text-shadow: none;
}
}
@keyframes ta-04-flicker2 {
0%, 30%, 32%, 80%, 82%, 100% {
opacity: 1;
text-shadow:
0 0 5px #fff, 0 0 10px #fff,
0 0 20px var(--pink), 0 0 40px var(--pink),
0 0 80px var(--pink), 0 0 90px var(--pink);
}
31%, 81% {
opacity: 0.3;
text-shadow: none;
}
}
@media (prefers-reduced-motion: reduce) {
.ta-04__sign span, .ta-04__label { animation: none; }
} .ta-04, .ta-04 *, .ta-04 *::before, .ta-04 *::after {
margin: 0; padding: 0; box-sizing: border-box;
}
.ta-04 ::selection { background: #fb7185; color: #fff; }
.ta-04 {
--bg: #030309;
--pink: #ff2d78;
min-height: 100vh;
background: var(--bg);
display: flex;
align-items: center;
justify-content: center;
padding: 2rem;
font-family: 'Syne', sans-serif;
}
.ta-04__stage { text-align: center; }
.ta-04__label {
font-size: 0.7rem;
letter-spacing: 0.4em;
text-transform: uppercase;
color: #ff2d78;
text-shadow:
0 0 4px #ff2d78,
0 0 12px #ff2d78;
margin-bottom: 0.5rem;
}
.ta-04__sign {
font-size: clamp(4rem, 12vw, 7rem);
font-weight: 900;
letter-spacing: 0.1em;
color: #fff;
display: flex;
gap: 0.05em;
}
.ta-04__sign span {
display: inline-block;
text-shadow:
0 0 5px #fff,
0 0 10px #fff,
0 0 20px var(--pink),
0 0 40px var(--pink),
0 0 80px var(--pink),
0 0 90px var(--pink);
}
.ta-04__s1 { animation: ta-04-flicker1 4.5s infinite; }
.ta-04__s2 { animation: ta-04-flicker2 3.8s infinite; color: #ff8fab; text-shadow:
0 0 5px #fff, 0 0 10px #fff, 0 0 20px #ff8fab, 0 0 40px #ff8fab, 0 0 80px #ff8fab; }
.ta-04__s3 { animation: ta-04-flicker1 5.2s 0.6s infinite; }
.ta-04__s4 { animation: ta-04-flicker2 4.1s 1.2s infinite; }
.ta-04__sub {
font-size: 0.68rem;
color: #2d1f2a;
margin-top: 1.2rem;
letter-spacing: 0.1em;
font-family: 'Courier New', monospace;
}
@keyframes ta-04-flicker1 {
0%, 19%, 21%, 23%, 25%, 54%, 56%, 100% {
opacity: 1;
text-shadow:
0 0 5px #fff, 0 0 10px #fff,
0 0 20px var(--pink), 0 0 40px var(--pink),
0 0 80px var(--pink), 0 0 90px var(--pink);
}
20%, 24%, 55% {
opacity: 0.4;
text-shadow: none;
}
}
@keyframes ta-04-flicker2 {
0%, 30%, 32%, 80%, 82%, 100% {
opacity: 1;
text-shadow:
0 0 5px #fff, 0 0 10px #fff,
0 0 20px var(--pink), 0 0 40px var(--pink),
0 0 80px var(--pink), 0 0 90px var(--pink);
}
31%, 81% {
opacity: 0.3;
text-shadow: none;
}
}
@media (prefers-reduced-motion: reduce) {
.ta-04__sign span, .ta-04__label { animation: none; }
}How this works
Neon glow is built by stacking multiple text-shadow values on a single element — typically four to six layers progressing from a tight coloured core (e.g., 0 0 5px) through intermediate blooms to a wide diffuse outer glow (0 0 80px). Each layer uses the same hue at increasing blur radii, creating the hot-centre-to-soft-edge falloff of a real neon tube.
The flicker animation keyframes rapidly toggle opacity and collapse the text-shadow to near-zero at irregular intervals — simulating the unstable gas discharge of a worn-out tube. Multiple named keyframes with different durations run on separate letters, staggered with animation-delay so each character flickers independently rather than the whole word cutting out simultaneously.
Customize
- Change the neon colour by replacing all hex values in the
text-shadowstack with a new hue — use the same colour at varying opacities fromffto33. - Increase glow radius by pushing the outermost shadow to
0 0 120pxor even0 0 200pxfor an environment-lighting effect on dark backgrounds. - Slow the flicker by increasing all
animation-durationvalues on individual letters, or remove the flicker entirely and keep just the static glow stack. - Add a sign-board framing by wrapping in a dark rectangle with
border: 2px solidin the glow colour andpadding: 1rem 2rem. - Combine with a
filter: blur(1px)on a::beforepseudo-element duplicate to simulate the diffuse light cast on the background behind the sign.
Watch out for
- Stacking more than 6–8 text-shadow layers triggers expensive repaint cycles on mobile; reduce to 3–4 layers at reduced sizes for performance.
- Text-shadow does not respect
overflow: hidden— the outer glow spreads beyond the element bounds, which can bleed into adjacent cards if the gallery container doesn't haveoverflow: hidden. - Very high blur radius values (>80px) render differently across browsers — Safari tends to show a harder falloff while Firefox and Chrome produce a softer bloom.
Browser support
| Chrome | Safari | Firefox | Edge |
|---|---|---|---|
| 4+ | 3.1+ | 3.5+ | 4+ |
text-shadow is universally supported; no modern browser concerns. GPU compositing varies by device for large blur values.