Flow

Effects / CSS

Vaporwave grid

An endless neon grid racing toward a striped retro sun on a purple horizon.

Prompt to build it

Build a vaporwave scene: a scrolling neon perspective grid toward a striped sunset sun. Use a repeating-linear-gradient grid on a plane with perspective and rotateX(60deg), animate background-position, and mask the sun with stripes. Make it responsive, cap devicePixelRatio at 2, pause when off-screen, and show a still frame when prefers-reduced-motion is set. No external libraries.

Tested code

One self-contained HTML file with no libraries: the same code that runs above. Your AI gets it from Flow's get_effect tool.

Show the code
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Vaporwave grid | Flow effect</title> <!-- Flow effect: Vaporwave grid (https://flow.donta.io/effects/vaporwave-grid) Self-contained: no libraries. Copy the .fx-stage element, the CSS and the script into your project and size .fx-stage however you like. --> <style> :root { --display: "Bricolage Grotesque", ui-sans-serif, system-ui, sans-serif; --body: ui-sans-serif, system-ui, sans-serif; } html, body { margin: 0; min-height: 100%; background: #0e0e10; display: grid; place-items: center; } .fx-stage { width: min(100vw, 960px); } /* Stage that every effect fills. Container units (cqw/cqmin) size the art. */ .fx-stage { position: relative; aspect-ratio: 4 / 3; overflow: hidden; border-radius: 16px; container-type: size; background: #111; isolation: isolate; } .fx-fill { position: absolute; inset: 0; } .fx-fallback { position: absolute; inset: 0; } .fx-center { display: grid; place-items: center; } /* ── Vaporwave ────────────────────────────────── */ .fx-vapor { background: linear-gradient(#12022b, #3a0a5e 48%, #8a1a7a 62%, #12022b 62%); perspective: 30cqh; } .fx-vapor-sun { position: absolute; left: 50%; top: 22%; width: 40cqmin; aspect-ratio: 1; translate: -50% 0; border-radius: 50%; background: linear-gradient(#ffe66b, #ff7a59 55%, #ff2fa8); -webkit-mask: linear-gradient(#000 52%, transparent 52% 56%, #000 56% 64%, transparent 64% 69%, #000 69% 76%, transparent 76% 82%, #000 82% 88%, transparent 88%); mask: linear-gradient(#000 52%, transparent 52% 56%, #000 56% 64%, transparent 64% 69%, #000 69% 76%, transparent 76% 82%, #000 82% 88%, transparent 88%); box-shadow: 0 0 12cqmin rgba(255, 80, 180, 0.6); } .fx-vapor-grid { position: absolute; left: -50%; right: -50%; top: 62%; height: 80cqh; transform-origin: top center; transform: rotateX(72deg); background-image: linear-gradient(#ff3fd0 2px, transparent 2px), linear-gradient(90deg, #ff3fd0 2px, transparent 2px); background-size: 7cqw 7cqw; animation: fx-grid 1.4s linear infinite; -webkit-mask: linear-gradient(transparent, #000 25%); mask: linear-gradient(transparent, #000 25%); } @keyframes fx-grid { to { background-position: 0 7cqw; } } .fx-vapor b { position: absolute; top: 7%; width: 100%; text-align: center; font: italic 800 9cqmin/1 var(--display); letter-spacing: 0.3em; color: #9ff6ff; text-shadow: 0 0 3cqmin #2fd8ff; } @media (prefers-reduced-motion: reduce) { .fx-stage *, .fx-stage *::before, .fx-stage *::after { animation-play-state: paused !important; } } </style> </head> <body> <div class="fx-stage"> <div class="fx-fill fx-vapor"><div class="fx-vapor-sun"></div><div class="fx-vapor-grid"></div><b>VAPOR</b></div> </div> </body> </html>

How it works

A grid drawn with repeating gradients is tilted with perspective and rotateX, and its background position scrolls; a sun with gradient stripes sits on the horizon.

Guardrails

  • Slow the grid scroll for long views; it's tiring at speed.
  • Respect prefers-reduced-motion: show a still frame instead of the animation.
  • Pause when off-screen or when the tab is hidden (IntersectionObserver + visibilitychange).
  • Keep text off busy animated areas, or give it a solid backing that passes WCAG contrast.
  • One showpiece effect per page. If everything moves, nothing stands out.