30 CSS Hover Effects 06 / 30

CSS Neon Glow Text Hover Effect

Six neon-sign-inspired text hover effects — classic tube glow, pulsing flicker, color-cycle sweep, multi-layer bloom, retro arcade, and icy frost glow — using layered text-shadow transitions to simulate electroluminescent lighting.

Pure CSS MIT licensed
Live Demo Open in tab

This is a full-page demo — interact inside the frame above, or open it in the playground for the full-screen experience.

Open in playground

The code

<div class="hv-06">
  <div class="hv-06__stack">
    <div class="hv-06__row">
      <span class="hv-06__neon hv-06__neon--classic">NEON</span>
      <span class="hv-06__label">classic tube glow</span>
    </div>
    <div class="hv-06__row">
      <span class="hv-06__neon hv-06__neon--flicker">FLICKER</span>
      <span class="hv-06__label">pulsing flicker</span>
    </div>
    <div class="hv-06__row">
      <span class="hv-06__neon hv-06__neon--cycle">SPECTRUM</span>
      <span class="hv-06__label">hue-rotate cycle</span>
    </div>
    <div class="hv-06__row">
      <span class="hv-06__neon hv-06__neon--bloom">BLOOM</span>
      <span class="hv-06__label">multi-layer bloom</span>
    </div>
    <div class="hv-06__row">
      <span class="hv-06__neon hv-06__neon--arcade">HI-SCORE</span>
      <span class="hv-06__label">retro arcade</span>
    </div>
    <div class="hv-06__row">
      <span class="hv-06__neon hv-06__neon--frost">ICE</span>
      <span class="hv-06__label">icy frost glow</span>
    </div>
  </div>
</div>
.hv-06,.hv-06 *,.hv-06 *::before,.hv-06 *::after{box-sizing:border-box;margin:0;padding:0}
.hv-06 ::selection{background:#ff00de;color:#fff}
.hv-06{
  --bg:#020204;
  --dim:#3a3a4a;
  font-family:'Segoe UI',system-ui,sans-serif;
  background:var(--bg);
  min-height:100vh;
  display:flex;align-items:center;justify-content:center;
  padding:60px 24px;
}
.hv-06__stack{
  display:flex;flex-direction:column;gap:12px;
  width:min(700px,100%);
}
.hv-06__row{
  display:flex;align-items:center;justify-content:space-between;
  padding:32px 40px;
  background:rgba(255,255,255,.02);
  border:1px solid rgba(255,255,255,.06);
  border-radius:12px;gap:20px;
}
.hv-06__label{font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--dim);white-space:nowrap;flex-shrink:0}

/* shared neon base */
.hv-06__neon{
  font-size:clamp(1.6rem,4vw,2.4rem);font-weight:700;letter-spacing:.15em;
  cursor:default;display:inline-block;
}

/* 1 — classic */
.hv-06__neon--classic{
  color:#ff00de;
  text-shadow:0 0 4px #ff00de44;
  transition:text-shadow .4s,color .4s;
}
.hv-06__neon--classic:hover{
  color:#fff;
  text-shadow:
    0 0 4px #fff,
    0 0 16px #ff00de,
    0 0 40px #ff00de,
    0 0 80px #ff00de;
}

/* 2 — flicker */
.hv-06__neon--flicker{
  color:#39ff14;
  transition:text-shadow .3s;
}
.hv-06__neon--flicker:hover{
  color:#fff;
  text-shadow:0 0 4px #fff,0 0 18px #39ff14,0 0 50px #39ff14;
  animation:hv-06-flicker 2s linear infinite;
}
@keyframes hv-06-flicker{
  0%,19%,21%,23%,25%,54%,56%,100%{
    text-shadow:0 0 4px #fff,0 0 18px #39ff14,0 0 50px #39ff14;
    color:#fff;
  }
  20%,24%,55%{
    text-shadow:none;color:#39ff14;
  }
}

/* 3 — hue-rotate cycle */
.hv-06__neon--cycle{
  color:#ff4400;
  text-shadow:0 0 4px #ff440033;
  transition:text-shadow .4s,filter .4s;
}
.hv-06__neon--cycle:hover{
  color:#fff;
  text-shadow:0 0 6px #fff,0 0 20px #ff4400,0 0 60px #ff4400;
  animation:hv-06-huerot 3s linear infinite;
}
@keyframes hv-06-huerot{
  0%{filter:hue-rotate(0deg)}
  100%{filter:hue-rotate(360deg)}
}

/* 4 — multi-layer bloom */
.hv-06__neon--bloom{
  color:#7c3aed;
  text-shadow:0 0 4px #7c3aed44;
  transition:text-shadow .5s cubic-bezier(.4,0,.2,1),color .5s;
}
.hv-06__neon--bloom:hover{
  color:#fff;
  text-shadow:
    0 0 2px #fff,
    0 0 8px #a78bfa,
    0 0 20px #7c3aed,
    0 0 50px #6d28d9,
    0 0 100px #5b21b6,
    0 0 180px #4c1d95;
}

/* 5 — retro arcade */
.hv-06__neon--arcade{
  color:#ffee00;font-family:monospace;
  text-shadow:0 0 4px #ffee0044;
  transition:text-shadow .25s steps(2),color .25s;
}
.hv-06__neon--arcade:hover{
  color:#fff;
  text-shadow:
    2px 2px 0 #ff6600,
    0 0 10px #ffee00,
    0 0 30px #ffee00,
    0 0 60px #ff6600;
}

/* 6 — frost */
.hv-06__neon--frost{
  color:#a5f3fc;
  text-shadow:0 0 4px #a5f3fc44;
  transition:text-shadow .5s,color .5s,letter-spacing .5s;
}
.hv-06__neon--frost:hover{
  color:#fff;letter-spacing:.25em;
  text-shadow:
    0 0 4px #fff,
    0 0 16px #a5f3fc,
    0 0 40px #0ea5e9,
    0 0 80px #0369a1;
}

@media(max-width:520px){.hv-06__row{flex-direction:column;align-items:flex-start}}
@media(prefers-reduced-motion:reduce){
  .hv-06__neon{transition:none!important;animation:none!important}
}

How this works

Neon glow on text is created by stacking multiple text-shadow values at increasing radii: a tight 0 0 4px for the hot inner core, a medium 0 0 20px for the diffuse halo, and a wide 0 0 60px for the ambient room bleed. Transitioning from text-shadow: none (or a dimmed version) to the full multi-layer shadow on hover gives the satisfying 'flick on' feeling of a real neon tube.

The flicker variant uses a @keyframes animation on the :hover state that randomly drops opacity at 92–96% of the cycle, matching the temporal frequency of a failing fluorescent starter. The color-cycle variant animates filter: hue-rotate() on the glowing text, which rotates the entire text-shadow color stack uniformly without needing to redeclare all the shadows.

Customize

  • Increase bloom radius by adding a fourth shadow at 0 0 120px var(--color) — the extra layer adds perceptible ambient fill against dark backgrounds.
  • Simulate a flicker fault by shortening the keyframe animation to .15s and using steps(2) timing for an abrupt hard-switch blink.
  • Change neon tube color by swapping the --neon custom property — all three shadow layers reference the same variable so one edit recolors everything.
  • Add a subtle color: #fff on hover to brighten the letterforms themselves, making them look like they're emitting light rather than being lit from behind.
  • Pair with a dark background-color: #000 on the container — neon glow only reads convincingly against very dark backgrounds; mid-tones kill the effect.

Watch out for

  • Animating text-shadow with many layers is GPU-expensive — limit continuous flicker animations to one element per viewport and pause off-screen instances.
  • filter: hue-rotate() on the hue-cycle variant affects all child elements including any non-text decorations — scope it tightly to the text element only.
  • On OLED screens neon glow looks excellent; on low-quality LCD panels with backlight bleed the subtle inner shadows may be imperceptible — increase the inner glow to 0 0 8px.

Browser support

ChromeSafariFirefoxEdge
60+ 10.1+ 55+ 60+

text-shadow transitions and filter: hue-rotate are universally supported — no compatibility concerns.

Search CodeFronts

Loading…