---
name: cyberpunk-neon
description: Use when you want "Edgy, futuristic, intense" - Combines dark surfaces, saturated neon, grids, and glow.
---

# Cyberpunk Neon

> **Category:** Premium / Futuristic  -  **Personality:** Edgy, futuristic, intense
>
> **Best use:** Gaming, cybersecurity, sci-fi
>
> **Ratings:** Professional 2/5 - Casual 3/5 - Exotic 5/5 - Visual impact 5/5 - Difficulty 3/5 - Performance cost 3/5

## What it is

A full neon UI scene, not just glowing text: near-black surfaces, a few **saturated** accent hues (cyan / magenta / lime), angular HUD panels with glowing edges, a receding perspective "grid floor", CRT scanlines, and a glitchy chrome title. It reads as a game launcher / cyber dashboard. Reach for it when the brand is gaming, e-sports, crypto, cybersecurity or sci-fi and the goal is maximum edge and energy — it is loud by design, so it is a poor fit for calm, corporate, or content-heavy reading UIs.

## Dependencies / CDN

None — pure CSS effect + a few lines of vanilla JS. The demo loads two display/body fonts (optional):

```html
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Oxanium:wght@600;700;800&family=Spline+Sans+Mono:wght@400;500&display=swap" rel="stylesheet">
```

## HTML

Decorative layers (`bg`, `scan`, `flash`, `corners`) are siblings of the UI, `aria-hidden`. The runner panel uses the double-element "neon frame" pattern; the title carries `data-text` for the glitch.

```html
<div class="cy-stage">
  <div class="cy-bg" aria-hidden="true">
    <span class="cy-orb o1"></span><span class="cy-orb o2"></span>
    <div class="cy-grid"></div>
  </div>
  <div class="cy-scan" aria-hidden="true"></div>

  <div class="cy-ui">
    <h2 class="cy-title">GHOST<span class="l2 cy-glitch" data-text="PROTOCOL">PROTOCOL</span></h2>

    <button class="cy-btn cy-play"><span>&#9654; Jack In</span></button>
    <button class="cy-btn cy-ghost"><span>Mission Brief &rarr;</span></button>

    <!-- neon-edged HUD panel: gradient frame + inset dark inner, same clip-path -->
    <div class="cy-frame"><div class="cy-inner">
      <h3>Runner Status</h3>
      <div class="cy-eq"><i style="--h:.5"></i><i style="--h:.9"></i><i style="--h:.4"></i><i style="--h:.8"></i></div>
    </div></div>
  </div>
</div>
```

## CSS

```css
/* palette + dark stage (a contained panel — never width:100vw) */
.cy-stage{
  --cy-cyan:#1ff0ff; --cy-mag:#ff2d7e; --cy-lime:#d8ff48; --cy-mut:#7e8ac0;
  position:relative; overflow:hidden; isolation:isolate; border-radius:24px; min-height:660px;
  color:#e3ebff; font-family:'Spline Sans Mono',monospace;
  background:radial-gradient(130% 95% at 12% -12%, #15183a 0%, #06060f 56%), #06060f;
}

/* 1) PERSPECTIVE GRID FLOOR — two gradients tilted back, faded at the horizon, scrolling forward */
.cy-grid{position:absolute; left:-22%; right:-22%; bottom:-2%; height:60%;
  background-image:linear-gradient(rgba(31,240,255,.15) 1px, transparent 1px),
                   linear-gradient(90deg, rgba(31,240,255,.15) 1px, transparent 1px);
  background-size:46px 46px;
  transform:perspective(440px) rotateX(67deg); transform-origin:50% 100%;
  -webkit-mask-image:linear-gradient(to top,#000 5%,transparent 88%);
          mask-image:linear-gradient(to top,#000 5%,transparent 88%);
  animation:cy-scroll 7s linear infinite}
@keyframes cy-scroll{to{background-position:0 46px}}
.cy-orb{position:absolute; border-radius:50%; filter:blur(86px); opacity:.5}
.cy-orb.o1{width:48%; height:46%; background:var(--cy-cyan); top:-15%; left:-7%}
.cy-orb.o2{width:46%; height:54%; background:var(--cy-mag); bottom:-18%; right:-9%; opacity:.42}

/* 2) CRT SCANLINES + sweep (over everything, never captures the pointer) */
.cy-scan{position:absolute; inset:0; z-index:5; pointer-events:none; opacity:.45;
  background:repeating-linear-gradient(0deg, transparent 0 2px, rgba(0,0,0,.5) 2px 3px)}
.cy-scan::after{content:""; position:absolute; left:0; right:0; height:30%;
  background:linear-gradient(180deg, transparent, rgba(31,240,255,.07), transparent);
  animation:cy-sweep 5.5s linear infinite}
@keyframes cy-sweep{0%{top:-32%}100%{top:102%}}

/* 3) NEON HUD PANEL — clip-path drops the border on the cut, so draw the edge with
      a gradient-filled outer + an inset dark inner sharing the SAME clip-path */
.cy-frame{--n:16px; position:relative; padding:1.5px;
  background:linear-gradient(150deg,var(--cy-cyan),rgba(31,240,255,.12) 38%,rgba(255,45,126,.3));
  clip-path:polygon(0 0,calc(100% - var(--n)) 0,100% var(--n),100% 100%,var(--n) 100%,0 calc(100% - var(--n)));
  filter:drop-shadow(0 22px 46px rgba(31,240,255,.28))}   /* glow follows the notch */
.cy-inner{background:linear-gradient(160deg,rgba(14,16,36,.97),rgba(7,8,18,.98)); padding:20px 22px;
  clip-path:polygon(0 0,calc(100% - var(--n)) 0,100% var(--n),100% 100%,var(--n) 100%,0 calc(100% - var(--n)))}

/* 4) NEON BUTTON — clip-path notch; glow via filter:drop-shadow (box-shadow would be clipped away) */
.cy-btn{--n:10px; position:relative; font-family:'Oxanium',sans-serif; font-weight:700;
  text-transform:uppercase; letter-spacing:.08em; border:0; padding:14px 26px; cursor:pointer;
  transition:transform .15s, filter .2s;
  clip-path:polygon(0 0,calc(100% - var(--n)) 0,100% var(--n),100% 100%,var(--n) 100%,0 calc(100% - var(--n)))}
.cy-btn:hover{transform:translateY(-2px)}
.cy-btn span{position:relative; z-index:1}
.cy-play{color:#04121a; background:linear-gradient(120deg,var(--cy-cyan),#9bfcff);
  filter:drop-shadow(0 0 16px rgba(31,240,255,.7))}
.cy-play:hover{filter:drop-shadow(0 0 28px rgba(31,240,255,.95)) brightness(1.05)}
.cy-ghost{color:var(--cy-cyan); background:var(--cy-cyan); filter:drop-shadow(0 0 14px rgba(31,240,255,.4))}
.cy-ghost::before{content:""; position:absolute; inset:1.5px; background:#0a0c1c; clip-path:inherit}

/* 5) GLITCH TITLE — two tinted copies of the text, offset, with jumping clip bands */
.cy-title{font-family:'Oxanium',sans-serif; font-weight:800; text-transform:uppercase;
  font-size:clamp(40px,6.4vw,72px); line-height:.92; margin:0; color:#fff;
  text-shadow:0 0 24px rgba(31,240,255,.4)}
.cy-title .l2{display:block; color:var(--cy-cyan)}
.cy-glitch{position:relative}
.cy-glitch::before,.cy-glitch::after{content:attr(data-text); position:absolute; top:0; left:0;
  width:100%; overflow:hidden; mix-blend-mode:screen}
.cy-glitch::before{color:var(--cy-mag); transform:translateX(-2px); animation:cy-gl1 3.2s steps(2) infinite}
.cy-glitch::after{color:var(--cy-cyan); transform:translateX(2px); animation:cy-gl2 2.7s steps(2) infinite}
@keyframes cy-gl1{0%,70%,100%{clip-path:inset(0 0 64% 0)}80%{clip-path:inset(42% 0 22% 0);transform:translate(-4px,1px)}}
@keyframes cy-gl2{0%,64%,100%{clip-path:inset(58% 0 0 0)}77%{clip-path:inset(76% 0 0 0);transform:translate(4px,0)}}

/* 6) EQUALIZER bars (HUD telemetry); --h drives both the animated peak and the static height */
.cy-eq{display:flex; align-items:flex-end; gap:3px; height:46px}
.cy-eq i{flex:1; transform-origin:bottom; transform:scaleY(var(--h));
  background:linear-gradient(180deg,var(--cy-cyan),rgba(31,240,255,.12)); box-shadow:0 0 8px -2px var(--cy-cyan);
  animation:cy-eq 1.05s ease-in-out infinite alternate}
@keyframes cy-eq{from{transform:scaleY(calc(var(--h) * .32))} to{transform:scaleY(var(--h))}}

/* CALM under reduced motion: kill every loop + the glitch, keep the neon styling */
@media(prefers-reduced-motion:reduce){
  .cy-grid,.cy-scan::after,.cy-eq i{animation:none}
  .cy-glitch::before,.cy-glitch::after{display:none}
  .cy-eq i{transform:scaleY(var(--h))}
}
```

## JavaScript

Optional. Two flourishes — a pointer parallax on the backdrop and a "Jack In" state toggle that flashes a glitch. Both are gated on `prefers-reduced-motion`.

```js
var stage=document.querySelector('.cy-stage');
var bg=stage.querySelector('.cy-bg');
var reduce=matchMedia('(prefers-reduced-motion: reduce)').matches;

if(bg && !reduce){
  stage.addEventListener('pointermove',function(e){
    var r=stage.getBoundingClientRect();
    var dx=((e.clientX-r.left)/r.width-.5)*-18, dy=((e.clientY-r.top)/r.height-.5)*-12;
    bg.style.transform='translate3d('+dx.toFixed(1)+'px,'+dy.toFixed(1)+'px,0)';
  });
  stage.addEventListener('pointerleave',function(){bg.style.transform='translate3d(0,0,0)';});
}

// re-trigger the .cy-boot glitch class on click (skip the flash when motion is reduced)
var play=stage.querySelector('.cy-play');
play && play.addEventListener('click',function(){
  if(reduce) return;
  stage.classList.remove('cy-boot'); void stage.offsetWidth; stage.classList.add('cy-boot');
});
```

## How it works

- **Neon = saturated hue on near-black + glow.** Glow on *text* is layered `text-shadow`; glow on *shapes* is `filter: drop-shadow()` (see Gotchas — `box-shadow` gets clipped by `clip-path`). Keep the palette to 2-3 accents so it reads cohesive, not like a rainbow.
- **Perspective grid floor:** two `repeating` linear-gradients make a grid; `transform: perspective() rotateX(67deg)` with `transform-origin:50% 100%` lays it flat like a floor; a top-fading `mask-image` sends it toward a horizon; animating `background-position` scrolls it toward the viewer (the classic synthwave road).
- **HUD panels:** `clip-path: polygon(...)` cuts the corners for that angular tech look. Because a `border` disappears along the diagonal cut, the lit edge is faked with a **double element** — a gradient-filled `.cy-frame` and a 1.5px-inset dark `.cy-inner` sharing the same clip.
- **Scanlines** are a repeating dark-line gradient over the whole stage; a translucent band sweeps top-to-bottom for CRT life. Both layers are `pointer-events:none`.
- **Glitch title** duplicates the text into `::before`/`::after` via `attr(data-text)`, tints them magenta/cyan, nudges them ±2px and reveals jumping horizontal bands with `clip-path: inset()` on a stepped keyframe → RGB split.

## Customization

- **Palette:** every colour is a `--cy-*` custom property on `.cy-stage` — swap cyan/magenta for amber+red (hazard), or cyan+lime (matrix).
- **Notch size:** the `--n` var per component controls how aggressive the cut corners are (`0` = plain rectangles).
- **Grid:** `background-size` = cell density; the `rotateX` angle = how flat the floor lies; `cy-scroll` duration = speed.
- **Glow intensity:** tune the blur radius / alpha in the `drop-shadow()` and `text-shadow` values. Drop the scanline `opacity` for a cleaner, less "CRT" look.

## Accessibility & performance

- **Reduced motion is handled:** the grid scroll, sweep, equalizer, flicker and the entire glitch are disabled under `prefers-reduced-motion: reduce`; the steady neon styling stays, so it stays on-brand but calm.
- **Contrast:** bright accents on near-black pass easily; keep the scanline layer subtle (`opacity ~.45`) so body text under it stays legible, and don't put long paragraphs in the neon accent colour.
- **GPU cost:** `filter: drop-shadow()`, large blurred orbs and `backdrop-filter` are GPU-bound — keep the count small and **never animate the blur radius** (animate `transform`/`opacity` instead). All decorative layers are `aria-hidden="true"`.

## Gotchas

- **`box-shadow` is clipped by `clip-path`.** A notched neon button/panel loses its outer glow — use `filter: drop-shadow()`, which follows the clipped alpha shape.
- **A `border` won't render along a `clip-path` diagonal.** For a neon edge on a cut-corner panel use the double-clip trick (gradient outer + inset dark inner), not `border`.
- **Glitch needs `data-text`** mirrored from the visible text, the element must be `position:relative`, and `mix-blend-mode:screen` reads best on dark.
- **The grid needs `transform-origin` at the bottom + a fade mask**, otherwise it looks like a flat tilted plane instead of a floor receding to a horizon.
- **Keep it a contained panel** (`overflow:hidden` + `border-radius`); never `width:100vw` or margin breakouts — they spawn horizontal scrollbars.
