20 CSS Animated Buttons 01 / 20

CSS Neon Glow Button

A neon-lit CTA button with a pulsing glow halo and colour-shifting outline, built entirely with CSS box-shadow animations and no JavaScript.

Pure CSS MIT licensed
Live Demo Open in tab
Open in playground

The code

<div class="ab-01">
  <div class="ab-01__scene">
    <p class="ab-01__label">Premium SaaS — Launch Your Project</p>
    <h2 class="ab-01__headline">Build faster.<br>Ship smarter.</h2>
    <p class="ab-01__sub">Join 50,000+ developers already on the platform.</p>
    <button class="ab-01__btn">Get Started Free</button>
    <p class="ab-01__hint">No credit card required · Cancel anytime</p>
  </div>
</div>
.ab-01,.ab-01 *,.ab-01 *::before,.ab-01 *::after{box-sizing:border-box;margin:0;padding:0}
.ab-01 ::selection{background:#b829ff;color:#fff}
.ab-01{
  --neon:#b829ff;
  --neon-dim:rgba(184,41,255,.35);
  --bg:#0a0010;
  --text:#e8d5ff;
  font-family:system-ui,sans-serif;
  background:var(--bg);
  min-height:100vh;
  display:flex;
  align-items:center;
  justify-content:center;
}
.ab-01__scene{
  text-align:center;
  padding:2.5rem 2rem;
  max-width:520px;
}
.ab-01__label{
  font-size:.72rem;
  letter-spacing:.18em;
  text-transform:uppercase;
  color:var(--neon);
  margin-bottom:.75rem;
  opacity:.8;
}
.ab-01__headline{
  font-size:clamp(1.8rem,4vw,2.6rem);
  font-weight:800;
  color:#fff;
  line-height:1.15;
  margin-bottom:.75rem;
}
.ab-01__sub{
  font-size:.95rem;
  color:var(--text);
  opacity:.7;
  margin-bottom:2rem;
}
.ab-01__btn{
  position:relative;
  display:inline-flex;
  align-items:center;
  gap:.5rem;
  padding:.85rem 2.4rem;
  font-size:1rem;
  font-weight:700;
  letter-spacing:.04em;
  color:#fff;
  background:transparent;
  border:2px solid var(--neon);
  border-radius:8px;
  cursor:pointer;
  outline:none;
  text-transform:uppercase;
  transition:color .3s,background .3s,border-color .3s,box-shadow .3s;
  box-shadow:0 0 8px var(--neon-dim),0 0 20px var(--neon-dim),inset 0 0 10px rgba(184,41,255,.08);
  animation:ab-01-pulse 2s ease-in-out infinite;
  will-change:box-shadow;
  text-shadow:0 0 8px rgba(184,41,255,.6);
}
.ab-01__btn:hover{
  background:var(--neon);
  color:#fff;
  box-shadow:0 0 16px var(--neon),0 0 40px var(--neon),0 0 80px var(--neon-dim),inset 0 0 16px rgba(255,255,255,.15);
  text-shadow:none;
  animation-play-state:paused;
}
.ab-01__btn:active{
  transform:scale(.97);
}
@keyframes ab-01-pulse{
  0%,100%{box-shadow:0 0 8px var(--neon-dim),0 0 20px var(--neon-dim),inset 0 0 10px rgba(184,41,255,.08)}
  50%{box-shadow:0 0 14px var(--neon),0 0 36px var(--neon-dim),0 0 60px rgba(184,41,255,.15),inset 0 0 16px rgba(184,41,255,.12)}
}
.ab-01__hint{
  margin-top:1rem;
  font-size:.78rem;
  color:var(--text);
  opacity:.45;
}
@media(prefers-reduced-motion:reduce){
  .ab-01__btn{animation:none}
}

How this works

The glow effect layers multiple box-shadow values on the button — an inset layer for inner luminance plus two outer rings with different blur radii. A @keyframes ab-01-pulse animation oscillates the shadow spread and opacity on a 2 s loop, giving the halo a breathing quality without touching the DOM. The outline is a transparent border that transitions to the accent colour on :hover, creating the classic neon tube look purely via CSS property transitions.

The text colour itself rides a subtle text-shadow transition so the label appears to emit light. will-change: box-shadow promotes the element to its own composite layer, keeping the animation smooth at 60 fps even alongside other page content. The prefers-reduced-motion media query pauses the pulse but preserves the hover glow for accessibility.

Customize

  • Change the glow colour by updating --neon (default #b829ff) — the box-shadow, border, and text-shadow all derive from this one variable.
  • Control pulse speed by editing animation-duration on .ab-01__btn (try 1s for urgency or 4s for ambient mood).
  • Add a second colour stop by duplicating the keyframe and interpolating to a second --neon-alt variable for a colour-cycling halo.
  • Increase glow size for hero placements by multiplying the box-shadow blur values (e.g. change 20px to 40px on the outer ring).
  • Remove the inner glow for a subtler look by deleting the inset 0 0 … shadow layer and keeping only the outer rings.

Watch out for

  • Very large box-shadow blur values (> 60px) can trigger sub-pixel painting jitter on Chrome/Windows with certain GPU drivers — test on target hardware.
  • Safari < 15.4 paints box-shadow changes on the main thread; combine with transform: translateZ(0) to force GPU compositing.
  • The pulsing halo adds to the stacking context — if the button is inside a position: relative container with overflow: hidden the outer glow will be clipped.

Browser support

ChromeSafariFirefoxEdge
69+ 12+ 62+ 69+

All features are broadly supported; only extreme blur values vary between GPU drivers.

Search CodeFronts

Loading…