EmpireUI
Get Pro
← Blog8 min read#vaporwave#card#css

Vaporwave Card in CSS: Neon Gradients, Grid Lines and Sunset Palettes

Build a vaporwave card in pure CSS — neon gradients, retro grid lines, sunset palettes. Step-by-step with code examples and Empire UI component tips.

neon pink and purple vaporwave card design with retro grid lines on dark background

What Makes a Card "Vaporwave"?

Vaporwave is an aesthetic that peaked culturally around 2012–2016 but has been staging a serious comeback in UI work. The visual language is pretty specific: magenta-to-cyan gradients, CRT-era typography, flat perspective grids bleeding into the horizon, and that washed-out pastel-on-dark palette that feels like a corrupted VHS tape. You either immediately get it or you don't.

For a card specifically, you're combining three core ingredients. A sunset gradient background — think hot pink at the top bleeding into deep violet or teal. A scanline or grid overlay that reads as "retro digital." And neon-colored text or borders that glow, because flat text looks out of place here. Get those three right and literally any content inside reads as vaporwave.

Honestly, the style is more forgiving than it looks. You don't need a full design system overhaul. A single card component with the right background, a 1px grid overlay, and a text-shadow on the title is enough to nail the vibe. That said, placement matters — drop a vaporwave card on a white background and it'll look like a mistake. It needs darkness around it to breathe.

Worth noting: vaporwave and glassmorphism occasionally get mixed together, and you can pull that off — a frosted glass card over a vaporwave gradient background is legitimately sick. But for this article we're treating vaporwave as its own standalone surface, no blur required.

The Sunset Gradient — Building the Background

The gradient is where the whole thing lives or dies. A classic vaporwave sunset goes from a warm magenta (#ff6ec7 or #ff2d78) at the top, through a midtone purple (#8b45ff or #6a0dad), down to a deep teal or cyan (#00d4ff) at the bottom. That specific color journey is the aesthetic. Swap in different hues and it starts looking like a generic dark card.

Here's the baseline CSS for a card background:

.vaporwave-card {
  background: linear-gradient(
    160deg,
    #ff2d78 0%,
    #8b45ff 45%,
    #00d4ff 100%
  );
  border-radius: 12px;
  padding: 32px;
  position: relative;
  overflow: hidden;
  color: #fff;
}

You want position: relative and overflow: hidden from the start — the grid overlay we're adding next needs to be absolutely positioned inside, and clipping it cleanly is half the battle. The 160deg angle tilts the gradient diagonally, which gives more visual energy than a straight top-to-bottom fall.

In practice, 160deg doesn't work for every layout. If you're building a horizontal card (landscape aspect ratio), try 120deg instead — the gradient sweeps left-to-right more naturally. Adjust the color stops too: 0% / 50% / 100% is a clean default but pushing the purple stop to 35% makes the sunset feel more dramatic.

Retro Grid Lines: The CSS That Sells the Retro

The grid is what separates a vaporwave card from a "colorful dark card." It's that 80s wireframe aesthetic — a perspective grid receding into the distance, flat lines on the bottom half, suggesting a digital horizon. You can fake this entirely in CSS with gradients and no SVG.

.vaporwave-card::before {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 50%;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.15) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.15) 1px, transparent 1px);
  background-size: 40px 40px;
  pointer-events: none;
  z-index: 0;
}

That gives you a flat grid. The cells are 40px × 40px — small enough to feel dense, large enough to read clearly at normal card sizes (around 320px wide). One more thing — if you want the perspective effect where lines converge toward a vanishing point, you'll need to layer in a perspective() transform or use an SVG. Pure CSS can't do real perspective projection on a gradient grid, which is an annoying limitation.

Quick aside: a simpler alternative to perspective grids is horizontal scanlines only. Just background-image: repeating-linear-gradient(0deg, transparent, transparent 18px, rgba(0,0,0,0.2) 18px, rgba(0,0,0,0.2) 20px) gives you CRT-style horizontal lines with zero performance cost. Looks great on small cards where the full grid would feel too busy.

Make sure your card content sits on a higher z-index than the ::before pseudo-element, otherwise the grid will sit on top of your text. A position: relative; z-index: 1 on the inner content wrapper handles it.

Neon Glow: Typography, Borders and Box Shadows

The glow is where CSS gets fun. text-shadow with multiple layers is the standard move — one tight white layer close to the text, then one or two wider colored layers that bleed out. It costs nothing in bundle size and works everywhere.

.vaporwave-card h2 {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  text-shadow:
    0 0 8px #fff,
    0 0 20px #ff2d78,
    0 0 40px #ff2d78,
    0 0 80px #8b45ff;
}

.vaporwave-card {
  border: 1px solid rgba(255, 255, 255, 0.25);
  box-shadow:
    0 0 0 1px rgba(255, 45, 120, 0.4),
    0 0 24px rgba(139, 69, 255, 0.5),
    0 0 60px rgba(0, 212, 255, 0.2),
    0 8px 32px rgba(0, 0, 0, 0.6);
}

The box-shadow on the card itself is doing double duty. The first layer (0 spread, small blur) adds a colored inset glow near the border. The second and third layers push wider to create that "screen bleed" effect. The last layer is a standard drop shadow for grounding — without it the card floats too much.

Look, you can go overboard with glow layers quickly. Three or four is the sweet spot. Past that you're adding render cost for a visual effect that gets imperceptibly stronger. On mobile especially, heavy box-shadow and text-shadow stacks can cause paint jank on scroll, so test on a real device before shipping 8 shadow layers.

For the font choice: monospace or wide geometric sans-serifs work best. font-family: 'Space Grotesk', monospace or just the system ui-monospace stack reads as appropriately digital. Adding letter-spacing: 0.08em and text-transform: uppercase to headings is doing a lot of the heavy lifting — those two properties alone shift a card from generic to era-coded.

Putting It All Together: Full Component Example

Here's the complete card, everything assembled. This works as a standalone CSS component or as the base for a React/Vue component:

<div class="vaporwave-card">
  <div class="card-content">
    <span class="card-tag">A E S T H E T I C S</span>
    <h2>Digital Horizon</h2>
    <p>Somewhere between nostalgia and the future, the grid never ends.</p>
    <button class="vaporwave-btn">Explore →</button>
  </div>
</div>
.vaporwave-card {
  background: linear-gradient(160deg, #ff2d78 0%, #8b45ff 45%, #00d4ff 100%);
  border-radius: 12px;
  padding: 32px;
  position: relative;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.25);
  box-shadow:
    0 0 0 1px rgba(255, 45, 120, 0.4),
    0 0 24px rgba(139, 69, 255, 0.5),
    0 0 60px rgba(0, 212, 255, 0.2),
    0 8px 32px rgba(0, 0, 0, 0.6);
  max-width: 360px;
}

.vaporwave-card::before {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  height: 50%;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.12) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.12) 1px, transparent 1px);
  background-size: 40px 40px;
  pointer-events: none;
  z-index: 0;
}

.card-content {
  position: relative;
  z-index: 1;
}

.card-tag {
  display: inline-block;
  font-size: 0.65rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: 12px;
}

.vaporwave-card h2 {
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
  margin: 0 0 12px;
  text-shadow:
    0 0 8px #fff,
    0 0 20px #ff2d78,
    0 0 40px #ff2d78;
}

.vaporwave-card p {
  color: rgba(255, 255, 255, 0.85);
  line-height: 1.6;
  margin: 0 0 24px;
}

.vaporwave-btn {
  background: transparent;
  border: 1px solid rgba(255, 255, 255, 0.6);
  color: #fff;
  padding: 10px 20px;
  border-radius: 4px;
  cursor: pointer;
  letter-spacing: 0.1em;
  font-size: 0.85rem;
  text-transform: uppercase;
  transition: box-shadow 0.2s ease, background 0.2s ease;
}

.vaporwave-btn:hover {
  background: rgba(255, 255, 255, 0.1);
  box-shadow: 0 0 16px rgba(255, 45, 120, 0.6);
}

That's the full thing. No JavaScript, no build step, no dependencies. Drop it on a dark page background (something like #0a0010 or #050818) and it'll land correctly. You can also check out the vaporwave component hub on Empire UI for pre-built React versions that extend this pattern with animation support.

One more thing — the button's border-radius: 4px is intentional. Vaporwave doesn't do fully rounded pill buttons. Hard corners or very slight rounding keeps the digital-era energy. Pill buttons read as modern SaaS, not 1986.

Animation: Scanline Flicker and Gradient Shift

Static vaporwave cards are good. Animated ones are better. Two animations that cost almost nothing to add: a scanline flicker and a slow gradient shift.

@keyframes scanline {
  0% { transform: translateY(-100%); }
  100% { transform: translateY(100%); }
}

.vaporwave-card::after {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(
    transparent,
    rgba(255, 255, 255, 0.08),
    transparent
  );
  animation: scanline 3s linear infinite;
  pointer-events: none;
  z-index: 2;
}

@keyframes gradientShift {
  0% { background-position: 0% 50%; }
  50% { background-position: 100% 50%; }
  100% { background-position: 0% 50%; }
}

.vaporwave-card.animated {
  background: linear-gradient(
    160deg,
    #ff2d78, #8b45ff, #00d4ff, #ff6ec7, #8b45ff
  );
  background-size: 300% 300%;
  animation: gradientShift 8s ease infinite;
}

The scanline uses a 4px tall translucent white strip sliding down the card every 3 seconds. Subtle but immediately readable as CRT-influenced. The gradient shift cycles through the extended color stops over 8 seconds — slow enough to feel ambient, not distracting.

Keep prefers-reduced-motion in mind. Wrap both animations in a media query:

@media (prefers-reduced-motion: reduce) {
  .vaporwave-card::after,
  .vaporwave-card.animated {
    animation: none;
  }
}

That's it — three lines and you've respected accessibility without stripping the effect entirely for users who want it. If you're already using Empire UI's gradient generator, you can prototype the animated gradient values there before committing them to code.

Pairing Vaporwave Cards with Other Styles

You might want to blend vaporwave with other aesthetics in the same UI — and some combos work, some really don't. Vaporwave and neobrutalism clash hard. Neobrutalism is about flat bold borders and raw contrast; vaporwave is about glow, gradients, and nostalgia. They fight.

Vaporwave and glassmorphism, on the other hand, can work beautifully if you're deliberate. Put a vaporwave gradient as a background element and stack a glass-effect card on top — the blurred content layer picks up the neon colors and looks stunning. The glassmorphism generator is useful here for dialing in the right blur and alpha values so the glass card reads cleanly over the vivid gradient beneath it.

Vaporwave and aurora are natural siblings. Both use multi-color gradients and a dark background; aurora just tends to be softer and more pastel. You can transition a UI from aurora to vaporwave territory just by cranking the saturation and adding neon glow — no structural changes required.

In practice, if you're building a dark-mode-first product that wants to feel expressive without going full cyberpunk, vaporwave is probably the smartest direction. It's recognizable, it photographs well for marketing assets, and there are enough component patterns already established that you're not inventing from scratch. The vaporwave style hub on Empire UI has the pre-built pieces if you'd rather not hand-roll every card from zero.

FAQ

Can I use vaporwave cards in a production UI, or is it too niche?

Totally production-viable — gaming, music, portfolio, and entertainment products use it constantly. Just make sure your surrounding UI context supports it; dropping a vaporwave card in a generic SaaS dashboard looks weird.

Does backdrop-filter work inside vaporwave cards?

Yes, you can stack glassmorphism on top of a vaporwave gradient. Set the gradient on a parent container, then apply backdrop-filter blur on the card itself. Just check Safari support for complex nested stacking contexts.

How do I handle the grid overlay on smaller screens?

Reduce the background-size on the grid from 40px to 24px or 20px at smaller breakpoints — the larger cells look too sparse at 280px card widths. A quick media query handles it cleanly.

What fonts work best with vaporwave cards?

Space Grotesk, VT323 (for a pixel/CRT feel), or any wide geometric sans. Add letter-spacing: 0.08em and text-transform: uppercase to whatever you pick — those two properties do more than the font family itself.

Free components in 40 styles
React & Tailwind, copy-paste ready.
Browse →

Read next

Vaporwave Card Design: Pastel Gradients, Grid Lines and ChromeVaporwave Typography in CSS: Neon Fonts, Chroma Shift, Retro GlowTailwind Gradient Text: bg-clip-text in Under 2 MinutesCSS text-shadow: Glow Effects, Neon Text and Layered Shadows