Text glows like a neon sign, flickering unevenly before it settles.
export function neonFlicker(el) {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return () => {}
el.classList.add('k-neon')
const easing = 'steps(1)'
// GSAP nests a 6-leg flicker burst inside an outer repeat with a long
// repeatDelay — built here as one set of keyframes: 6 alternating legs
// (each carrying the real ease) packed into the front of the cycle,
// followed by a flat hold for the "repeatDelay" portion.
const legs = 6
const holdUnits = 8
const totalUnits = legs + holdUnits
const keyframes = []
for (let i = 0; i <= legs; i++) {
const kf = { opacity: i % 2 === 0 ? 1 : 0.3, offset: i / totalUnits }
if (i > 0) kf.easing = easing
keyframes.push(kf)
}
keyframes.push({ opacity: 1, offset: 1 })
const anim = el.animate(keyframes, {
duration: totalUnits * 0.1 * 1000,
delay: 0 * 1000,
iterations: Infinity,
fill: 'backwards',
})
return () => {
anim.cancel()
el.classList.remove('k-neon')
}
}
/* CSS */
.k-neon {
color: var(--text);
text-shadow: 0 0 4px var(--accent), 0 0 12px var(--accent), 0 0 24px var(--accent);
}