30 CSS Text Animations21 / 30

Pure CSSMIT licensed

CSS Glowing Neon Sign Text Flicker Animation

Believable neon, not just text-shadow spam: a script cocktail sign on brick where one letter buzzes with irregular dropout while the rest of the tube hums, and a power-on sequence where a two-tone diner sign ignites word by word and settles into a steady glow.

Published Updated

Live Demo
Try it

The code

<div class="cat-21-group">
<link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet">
<section class="cat-21a" aria-label="Neon cocktail sign with flickering letter">
  <div class="cat-21a__wall">
    <h1 class="cat-21a__sign" aria-label="Open Late"><span>Open&nbsp;La</span><span class="cat-21a__dying">t</span><span>e</span></h1>
    <p class="cat-21a__tag" aria-hidden="true">COCKTAILS · VINYL · UNTIL 4AM</p>
  </div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-21b" aria-label="Neon diner sign powering on">
  <div class="cat-21b__frame">
    <h1 class="cat-21b__sign"><span class="cat-21b__word cat-21b__word--pink" style="--i:0">NEON</span> <span class="cat-21b__word cat-21b__word--cyan" style="--i:1">DINER</span></h1>
    <p class="cat-21b__sub" aria-hidden="true">each word ignites, stutters, then holds steady</p>
  </div>
</section>
</div>
.cat-21-group {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  width: 100%;
}

.cat-21-group > section {
  flex: 1 1 480px;
  min-width: min(100%,360px);
}

.cat-21a,
.cat-21a *,
.cat-21a *::before,
.cat-21a *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-21a {
  --pink: #ff5fd2;
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: #140d10;
  background-image: repeating-linear-gradient(0deg,rgba(255,255,255,.035) 0 2px,transparent 2px 26px),repeating-linear-gradient(90deg,rgba(255,255,255,.025) 0 2px,transparent 2px 58px),radial-gradient(120% 90% at 50% 10%,#241318,#12090d 70%);
}

.cat-21a__wall {
  text-align: center;
  padding: 60px 40px;
  border-radius: 20px;
  background: radial-gradient(80% 70% at 50% 35%,rgba(255,95,210,.08),transparent 70%);
}

.cat-21a__sign {
  font-family: 'Pacifico',cursive;
  font-weight: 400;
  font-size: clamp(52px,9.5vw,120px);
  color: #ffe9fa;
  text-shadow: 0 0 4px #fff,0 0 11px var(--pink),0 0 26px var(--pink),0 0 58px color-mix(in oklab,var(--pink) 80%,transparent),0 0 110px color-mix(in oklab,var(--pink) 55%,transparent);
  animation: cat-21a-hum 3.4s ease-in-out infinite;
}

.cat-21a__dying {
  display: inline-block;
  animation: cat-21a-buzz 4.2s linear infinite;
}

.cat-21a__tag {
  margin-top: 26px;
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .42em;
  color: rgba(255,210,240,.5);
}

@keyframes cat-21a-hum {
  0%,
    100% {
    filter: brightness(1);
  }

  50% {
    filter: brightness(1.13);
  }
}

@keyframes cat-21a-buzz {
  0%,
    6.8%,
    7.4%,
    30%,
    31.4%,
    52%,
    53.5%,
    79%,
    82%,
    100% {
    opacity: 1;
    color: #ffe9fa;
    text-shadow: inherit;
  }

  7%,
    31%,
    52.6%,
    80%,
    81% {
    opacity: .28;
    color: rgba(255,180,225,.35);
    text-shadow: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-21a__sign,
    .cat-21a__dying {
    animation: none;
  }
}

.cat-21b,
.cat-21b *,
.cat-21b *::before,
.cat-21b *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-21b {
  --pink: #ff4fa8;
  --cyan: #2ee6ff;
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: radial-gradient(110% 90% at 50% 8%,#101622,#080b12 72%);
}

.cat-21b__frame {
  text-align: center;
  padding: 56px clamp(28px,7vw,90px);
  border: 2px solid rgba(255,255,255,.07);
  border-radius: 26px;
  box-shadow: inset 0 0 60px rgb(0 0 0/.6);
}

.cat-21b__sign {
  font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
  font-size: clamp(46px,9vw,110px);
  font-weight: 900;
  letter-spacing: .06em;
  line-height: 1.1;
}

.cat-21b__word {
  display: inline-block;
  animation: cat-21b-on 2.6s cubic-bezier(.3,.7,.3,1) calc(var(--i)*1.1s + .3s) both;
}

.cat-21b__word--pink {
  --c: var(--pink);
  color: #ffe6f3;
}

.cat-21b__word--cyan {
  --c: var(--cyan);
  color: #e3fbff;
}

.cat-21b__sub {
  margin-top: 24px;
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .2em;
  color: rgba(200,220,240,.4);
}

@keyframes cat-21b-on {
  0%,
    14% {
    color: rgba(255,255,255,.16);
    text-shadow: none;
  }

  15%,
    17% {
    color: inherit;
    text-shadow: 0 0 4px #fff,0 0 14px var(--c);
  }

  18%,
    26% {
    color: rgba(255,255,255,.16);
    text-shadow: none;
  }

  27%,
    34% {
    color: inherit;
    text-shadow: 0 0 4px #fff,0 0 14px var(--c);
  }

  35%,
    39% {
    color: rgba(255,255,255,.2);
    text-shadow: none;
  }

  40%,
    100% {
    color: inherit;
    text-shadow: 0 0 5px #fff,0 0 13px var(--c),0 0 30px var(--c),0 0 64px color-mix(in oklab,var(--c) 75%,transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-21b__word {
    animation: cat-21b-steady .4s ease both;
  }
}

@keyframes cat-21b-steady {
  to {
    text-shadow: 0 0 5px #fff,0 0 13px var(--c),0 0 30px var(--c);
  }
}
/* No JavaScript — a five-layer text-shadow builds the tube glow; one letter span runs an irregular-percentage dropout keyframe like a dying tube while the sign hums. */

/* No JavaScript — a single power-on keyframe (dark → stutter → steady glow) plays per word, offset 1.1s apart via --i; reduced motion jumps straight to steady. */
Paste this into ChatGPT, Claude, Cursor, or any coding assistant. The block below is pre-framed with everything the AI needs to integrate this demo into your project — markup, styles, scoping notes, and the source URL. Hit Copy and paste straight into your chat.
Here's a working CSS Text Animation from CodeFronts. Use it as-is or adapt to your framework. All classes are scoped under a unique prefix so the code won't collide with your existing styles. MIT licensed.
Demo: CSS Glowing Neon Sign Text Flicker Animation
Source: https://codefronts.com/motion/css-text-animations/css-neon-glow-text-animation/

Believable neon, not just text-shadow spam: a script cocktail sign on brick where one letter buzzes with irregular dropout while the rest of the tube hums, and a power-on sequence where a two-tone diner sign ignites word by word and settles into a steady glow.
## HTML
```html
<div class="cat-21-group">
<link href="https://fonts.googleapis.com/css2?family=Pacifico&display=swap" rel="stylesheet">
<section class="cat-21a" aria-label="Neon cocktail sign with flickering letter">
  <div class="cat-21a__wall">
    <h1 class="cat-21a__sign" aria-label="Open Late"><span>Open&nbsp;La</span><span class="cat-21a__dying">t</span><span>e</span></h1>
    <p class="cat-21a__tag" aria-hidden="true">COCKTAILS · VINYL · UNTIL 4AM</p>
  </div>
</section>
<link href="https://fonts.googleapis.com/css2?family=Archivo:ital,wght@0,500..900;1,500..900&display=swap" rel="stylesheet">
<section class="cat-21b" aria-label="Neon diner sign powering on">
  <div class="cat-21b__frame">
    <h1 class="cat-21b__sign"><span class="cat-21b__word cat-21b__word--pink" style="--i:0">NEON</span> <span class="cat-21b__word cat-21b__word--cyan" style="--i:1">DINER</span></h1>
    <p class="cat-21b__sub" aria-hidden="true">each word ignites, stutters, then holds steady</p>
  </div>
</section>
</div>
```
## CSS
```css
.cat-21-group {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  width: 100%;
}

.cat-21-group > section {
  flex: 1 1 480px;
  min-width: min(100%,360px);
}

.cat-21a,
.cat-21a *,
.cat-21a *::before,
.cat-21a *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-21a {
  --pink: #ff5fd2;
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: #140d10;
  background-image: repeating-linear-gradient(0deg,rgba(255,255,255,.035) 0 2px,transparent 2px 26px),repeating-linear-gradient(90deg,rgba(255,255,255,.025) 0 2px,transparent 2px 58px),radial-gradient(120% 90% at 50% 10%,#241318,#12090d 70%);
}

.cat-21a__wall {
  text-align: center;
  padding: 60px 40px;
  border-radius: 20px;
  background: radial-gradient(80% 70% at 50% 35%,rgba(255,95,210,.08),transparent 70%);
}

.cat-21a__sign {
  font-family: 'Pacifico',cursive;
  font-weight: 400;
  font-size: clamp(52px,9.5vw,120px);
  color: #ffe9fa;
  text-shadow: 0 0 4px #fff,0 0 11px var(--pink),0 0 26px var(--pink),0 0 58px color-mix(in oklab,var(--pink) 80%,transparent),0 0 110px color-mix(in oklab,var(--pink) 55%,transparent);
  animation: cat-21a-hum 3.4s ease-in-out infinite;
}

.cat-21a__dying {
  display: inline-block;
  animation: cat-21a-buzz 4.2s linear infinite;
}

.cat-21a__tag {
  margin-top: 26px;
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .42em;
  color: rgba(255,210,240,.5);
}

@keyframes cat-21a-hum {
  0%,
    100% {
    filter: brightness(1);
  }

  50% {
    filter: brightness(1.13);
  }
}

@keyframes cat-21a-buzz {
  0%,
    6.8%,
    7.4%,
    30%,
    31.4%,
    52%,
    53.5%,
    79%,
    82%,
    100% {
    opacity: 1;
    color: #ffe9fa;
    text-shadow: inherit;
  }

  7%,
    31%,
    52.6%,
    80%,
    81% {
    opacity: .28;
    color: rgba(255,180,225,.35);
    text-shadow: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-21a__sign,
    .cat-21a__dying {
    animation: none;
  }
}

.cat-21b,
.cat-21b *,
.cat-21b *::before,
.cat-21b *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cat-21b {
  --pink: #ff4fa8;
  --cyan: #2ee6ff;
  width: 100%;
  min-height: 100vh;
  display: grid;
  place-items: center;
  padding: 48px 24px;
  background: radial-gradient(110% 90% at 50% 8%,#101622,#080b12 72%);
}

.cat-21b__frame {
  text-align: center;
  padding: 56px clamp(28px,7vw,90px);
  border: 2px solid rgba(255,255,255,.07);
  border-radius: 26px;
  box-shadow: inset 0 0 60px rgb(0 0 0/.6);
}

.cat-21b__sign {
  font-family: 'Archivo','Segoe UI',system-ui,sans-serif;
  font-size: clamp(46px,9vw,110px);
  font-weight: 900;
  letter-spacing: .06em;
  line-height: 1.1;
}

.cat-21b__word {
  display: inline-block;
  animation: cat-21b-on 2.6s cubic-bezier(.3,.7,.3,1) calc(var(--i)*1.1s + .3s) both;
}

.cat-21b__word--pink {
  --c: var(--pink);
  color: #ffe6f3;
}

.cat-21b__word--cyan {
  --c: var(--cyan);
  color: #e3fbff;
}

.cat-21b__sub {
  margin-top: 24px;
  font-family: ui-monospace,Menlo,monospace;
  font-size: 11px;
  letter-spacing: .2em;
  color: rgba(200,220,240,.4);
}

@keyframes cat-21b-on {
  0%,
    14% {
    color: rgba(255,255,255,.16);
    text-shadow: none;
  }

  15%,
    17% {
    color: inherit;
    text-shadow: 0 0 4px #fff,0 0 14px var(--c);
  }

  18%,
    26% {
    color: rgba(255,255,255,.16);
    text-shadow: none;
  }

  27%,
    34% {
    color: inherit;
    text-shadow: 0 0 4px #fff,0 0 14px var(--c);
  }

  35%,
    39% {
    color: rgba(255,255,255,.2);
    text-shadow: none;
  }

  40%,
    100% {
    color: inherit;
    text-shadow: 0 0 5px #fff,0 0 13px var(--c),0 0 30px var(--c),0 0 64px color-mix(in oklab,var(--c) 75%,transparent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cat-21b__word {
    animation: cat-21b-steady .4s ease both;
  }
}

@keyframes cat-21b-steady {
  to {
    text-shadow: 0 0 5px #fff,0 0 13px var(--c),0 0 30px var(--c);
  }
}
```

## JavaScript
```js
/* No JavaScript — a five-layer text-shadow builds the tube glow; one letter span runs an irregular-percentage dropout keyframe like a dying tube while the sign hums. */

/* No JavaScript — a single power-on keyframe (dark → stutter → steady glow) plays per word, offset 1.1s apart via --i; reduced motion jumps straight to steady. */
```

How this works

Realism comes from three details. First, a layered glow: a tight white-hot core, a saturated mid halo, then wide soft bloom — five shadows, increasing blur. Second, an unlit state that still shows glass: dim, desaturated fill rather than pure transparency. Third, irregularity — flicker keyframes at uneven percentages so the dropout never feels metronomic:

@keyframes buzz{0%,7%,9%,31%,33%,78%,100%{
    opacity:1;text-shadow:var(--glow)}
  8%,32%,79%,84%{opacity:.35;text-shadow:none}}

Only one letter (a separate span) runs the dropout — exactly like a dying tube — while the whole sign breathes with a slow hum pulse. The diner variant sequences animation-delay per word for the classic switch-on.

Make it yours

  • Tube color: keep the core near-white and push hue into the mid halo — real neon reads white-hot at center.
  • Buzz frequency: add/remove dropout percentages; sparser = moodier.
  • Power-on order: randomize delays (not left-to-right) for found-sign character.
  • Pair hues per line (pink script + cyan block) like real two-circuit signs.

Gotchas — read before shipping

  • Five shadows on huge text is fine; five shadows animating on long paragraphs is not — flicker opacity, not the shadow stack, where possible.
  • Keep contrast at the dimmest flicker frame — the copy must stay legible mid-dropout.
  • Reduced motion: steady glow, zero flicker (strobe-like flashes are a vestibular trigger).

Browser support

ChromeSafariFirefoxEdge
111+16.2+113+111+

Floor set by color-mix() as this demo is written. The core technique itself goes back further — Chrome 26+.

text-shadow stacks are universal. The whole scene (brick, vignette) is CSS gradients — no images to license.

Search CodeFronts

Loading…