20 CSS Neon Text Effects09 / 20

Pure CSSMIT licensed

Neon Text Outline Stroke Animation

Hollow letters whose interiors stay dark while only the glass border glows — using -webkit-text-stroke — then an animated 'power-on' that lights the outline segment by segment. The exact hollow-tube look devs search for.

Published

Live Demo
Try it

The code

<div class="cnt-09">
  <h2 class="cnt-09__word" aria-label="VOLTAGE">
    <span style="--i:0">V</span><span style="--i:1">O</span><span style="--i:2">L</span><span style="--i:3">T</span><span style="--i:4">A</span><span style="--i:5">G</span><span style="--i:6">E</span>
  </h2>
</div>
.cnt-09,
.cnt-09 *,
.cnt-09 *::before,
.cnt-09 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cnt-09 ::selection {
  background: oklch(0.85 0.18 85);
  color: #140f02;
}

.cnt-09 {
  --accent: oklch(0.85 0.19 85);
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  background: radial-gradient(110% 110% at 50% 30%,#12100a,#060503);
}

.cnt-09__word {
  display: flex;
  gap: .04em;
  font-size: clamp(52px,13vw,128px);
  font-weight: 900;
  letter-spacing: .02em;
}

.cnt-09__word span {
  color: transparent;
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 2px color-mix(in oklch,var(--accent) 22%,#2a2410);
  animation: cnt-09-strike 1.2s ease forwards;
  animation-delay: calc(var(--i) * .16s);
}

@keyframes cnt-09-strike {
  0% {
    -webkit-text-stroke-color: color-mix(in oklch,var(--accent) 18%,#2a2410);
    text-shadow: none;
  }

  55% {
    -webkit-text-stroke-color: #fff;
    text-shadow: 0 0 6px #fff,0 0 16px var(--accent);
  }

  100% {
    -webkit-text-stroke-color: var(--accent);
    text-shadow: 0 0 5px #fff,0 0 14px var(--accent),0 0 34px var(--accent),0 0 66px var(--accent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cnt-09__word span {
    animation: none;
    -webkit-text-stroke-color: var(--accent);
    text-shadow: 0 0 5px #fff,0 0 14px var(--accent),0 0 34px var(--accent);
  }
}
/* No JavaScript — hollow -webkit-text-stroke + a per-letter power-on @keyframes. */
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 Neon Text Effect 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: Neon Text Outline Stroke Animation
Source: https://codefronts.com/motion/css-neon-text-effect/neon-text-outline-stroke-animation/

Hollow letters whose interiors stay dark while only the glass border glows — using -webkit-text-stroke — then an animated 'power-on' that lights the outline segment by segment. The exact hollow-tube look devs search for.
## HTML
```html
<div class="cnt-09">
  <h2 class="cnt-09__word" aria-label="VOLTAGE">
    <span style="--i:0">V</span><span style="--i:1">O</span><span style="--i:2">L</span><span style="--i:3">T</span><span style="--i:4">A</span><span style="--i:5">G</span><span style="--i:6">E</span>
  </h2>
</div>
```
## CSS
```css
.cnt-09,
.cnt-09 *,
.cnt-09 *::before,
.cnt-09 *::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

.cnt-09 ::selection {
  background: oklch(0.85 0.18 85);
  color: #140f02;
}

.cnt-09 {
  --accent: oklch(0.85 0.19 85);
  font-family: 'Segoe UI',system-ui,sans-serif;
  width: 100%;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 60px 20px;
  background: radial-gradient(110% 110% at 50% 30%,#12100a,#060503);
}

.cnt-09__word {
  display: flex;
  gap: .04em;
  font-size: clamp(52px,13vw,128px);
  font-weight: 900;
  letter-spacing: .02em;
}

.cnt-09__word span {
  color: transparent;
  -webkit-text-fill-color: transparent;
  -webkit-text-stroke: 2px color-mix(in oklch,var(--accent) 22%,#2a2410);
  animation: cnt-09-strike 1.2s ease forwards;
  animation-delay: calc(var(--i) * .16s);
}

@keyframes cnt-09-strike {
  0% {
    -webkit-text-stroke-color: color-mix(in oklch,var(--accent) 18%,#2a2410);
    text-shadow: none;
  }

  55% {
    -webkit-text-stroke-color: #fff;
    text-shadow: 0 0 6px #fff,0 0 16px var(--accent);
  }

  100% {
    -webkit-text-stroke-color: var(--accent);
    text-shadow: 0 0 5px #fff,0 0 14px var(--accent),0 0 34px var(--accent),0 0 66px var(--accent);
  }
}

@media (prefers-reduced-motion: reduce) {
  .cnt-09__word span {
    animation: none;
    -webkit-text-stroke-color: var(--accent);
    text-shadow: 0 0 5px #fff,0 0 14px var(--accent),0 0 34px var(--accent);
  }
}
```

## JavaScript
```js
/* No JavaScript — hollow -webkit-text-stroke + a per-letter power-on @keyframes. */
```

How this works

The fill is transparent (-webkit-text-fill-color: transparent) and the letterform is drawn purely by -webkit-text-stroke, so the inside of each glyph stays empty like a real bent tube. The glow lives on text-shadow hugging that stroke.

The 'power-on' is a @keyframes that ramps the stroke from a dim, near-invisible colour up to a bright charged one while the shadow blooms in — sequenced with a per-letter animation-delay using inline custom properties so the word strikes left-to-right like a sign warming up.

Make it yours

  • Thicken or thin the tube via -webkit-text-stroke-width (0.5px hairline → 3px chunky).
  • Retint with --accent; charged and dim states derive from it with color-mix().
  • Change the strike order/tempo by editing each letter's --i and the base delay.
  • Loop it (add infinite) for a sign that keeps re-striking, or run once for an intro.

Gotchas — read before shipping

  • -webkit-text-stroke is unprefixed nowhere yet — it's still a -webkit- property, but supported across all current engines including Firefox.
  • Hollow text has low contrast; keep the stroke bright enough to stay legible against the dark plate.
  • Per-letter animation needs each glyph in its own element (spans) — fine for a short headline, not body copy.

Browser support

ChromeSafariFirefoxEdge
111+16.2+113+111+

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

-webkit-text-stroke works in all current browsers (still -webkit-prefixed); text-shadow universal.

Techniques used in this demo

Search CodeFronts

Loading…