Retro Perspective Grid
Original · freeA launch and waitlist section set over an infinite neon grid that scrolls into a glowing horizon with rising particles.
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/bg-retro-grid.json"use client";
import { motion, useReducedMotion, type Variants } from "motion/react";
const gridImage =
"linear-gradient(to right, currentColor 1px, transparent 1px), linear-gradient(to bottom, currentColor 1px, transparent 1px)";
const fade: Variants = {
hidden: { opacity: 0, y: 20 },
show: (i: number) => ({
opacity: 1,
y: 0,
transition: { duration: 0.6, delay: i * 0.1, ease: [0.22, 1, 0.36, 1] },
}),
};
const particles = [
{ left: "14%", delay: "0s", dur: "7s", size: "h-1.5 w-1.5" },
{ left: "34%", delay: "-3s", dur: "9s", size: "h-1 w-1" },
{ left: "52%", delay: "-1.5s", dur: "8s", size: "h-1.5 w-1.5" },
{ left: "71%", delay: "-4.5s", dur: "10s", size: "h-1 w-1" },
{ left: "88%", delay: "-2s", dur: "7.5s", size: "h-1.5 w-1.5" },
];
export default function BgRetroGrid() {
const reduce = useReducedMotion();
return (
<section className="relative isolate flex min-h-[640px] w-full items-center justify-center overflow-hidden bg-white px-6 py-24 dark:bg-slate-950">
<style>{`
@keyframes brg-scroll { from { background-position: 0 0, 0 0; } to { background-position: 0 48px, 0 48px; } }
@keyframes brg-rise { 0% { transform: translateY(0); opacity: 0; } 12% { opacity: 1; } 88% { opacity: 1; } 100% { transform: translateY(-260px); opacity: 0; } }
@keyframes brg-pulse { 0%,100% { opacity: 0.55; transform: translate(-50%,-50%) scale(1); } 50% { opacity: 0.85; transform: translate(-50%,-50%) scale(1.12); } }
.brg-grid { animation: brg-scroll 2s linear infinite; }
.brg-particle { animation: brg-rise linear infinite; }
.brg-glow { animation: brg-pulse 6s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
.brg-grid, .brg-particle, .brg-glow { animation: none !important; }
}
`}</style>
{/* perspective floor grid */}
<div
aria-hidden="true"
className="pointer-events-none absolute inset-0 -z-10 overflow-hidden"
>
<div className="absolute bottom-0 left-1/2 h-[70%] w-[320%] -translate-x-1/2 [perspective:900px]">
<div
className="brg-grid absolute inset-0 origin-bottom text-indigo-500/25 [transform:rotateX(72deg)] dark:text-indigo-400/20"
style={{
backgroundImage: gridImage,
backgroundSize: "48px 48px",
maskImage: "linear-gradient(to top, black 8%, transparent 78%)",
WebkitMaskImage: "linear-gradient(to top, black 8%, transparent 78%)",
}}
/>
</div>
{/* horizon glow */}
<div className="brg-glow absolute left-1/2 top-1/2 h-44 w-[78%] rounded-full bg-indigo-500/25 blur-3xl dark:bg-indigo-500/30" />
{/* rising particles */}
<div className="absolute inset-x-0 bottom-1/4 top-1/4">
{!reduce &&
particles.map((p, i) => (
<span
key={i}
className={`brg-particle absolute bottom-0 rounded-full bg-indigo-500 shadow-[0_0_12px_2px_rgba(99,102,241,0.6)] dark:bg-indigo-300 ${p.size}`}
style={{ left: p.left, animationDelay: p.delay, animationDuration: p.dur }}
/>
))}
</div>
</div>
<div className="relative mx-auto max-w-2xl text-center">
<motion.span
custom={0}
variants={fade}
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.4 }}
className="inline-flex items-center gap-2 rounded-full border border-indigo-200 bg-indigo-50/70 px-4 py-1.5 text-xs font-semibold uppercase tracking-widest text-indigo-600 backdrop-blur dark:border-indigo-400/20 dark:bg-indigo-500/10 dark:text-indigo-300"
>
<svg
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
strokeWidth={2}
strokeLinecap="round"
strokeLinejoin="round"
aria-hidden="true"
className="h-3.5 w-3.5"
>
<path d="M13 2 3 14h7l-1 8 10-12h-7z" />
</svg>
Built for velocity
</motion.span>
<motion.h1
custom={1}
variants={fade}
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.4 }}
className="mt-6 text-4xl font-semibold tracking-tight text-slate-900 sm:text-6xl dark:text-white"
>
Ship on an infinite grid
</motion.h1>
<motion.p
custom={2}
variants={fade}
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.4 }}
className="mx-auto mt-5 max-w-lg text-base leading-relaxed text-slate-600 sm:text-lg dark:text-slate-400"
>
A receding neon grid gives your launch page endless depth while your
message stays crisp and centred at the horizon.
</motion.p>
<motion.form
custom={3}
variants={fade}
initial="hidden"
whileInView="show"
viewport={{ once: true, amount: 0.4 }}
onSubmit={(e) => e.preventDefault()}
className="mx-auto mt-9 flex w-full max-w-md flex-col gap-3 sm:flex-row"
>
<label htmlFor="brg-email" className="sr-only">
Email address
</label>
<input
id="brg-email"
type="email"
required
placeholder="you@example.com"
className="w-full flex-1 rounded-full border border-slate-300 bg-white/80 px-5 py-3 text-sm text-slate-900 shadow-sm outline-none backdrop-blur transition placeholder:text-slate-400 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/30 dark:border-white/15 dark:bg-white/5 dark:text-white dark:placeholder:text-slate-500"
/>
<button
type="submit"
className="inline-flex items-center justify-center gap-2 rounded-full bg-indigo-600 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-500/25 transition hover:bg-indigo-500 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:focus-visible:ring-offset-slate-950"
>
Join waitlist
</button>
</motion.form>
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Aurora Blobs Background
OriginalAn animated hero section with soft, ever-drifting aurora gradient blobs floating behind staggered, blur-in content.

Conic Gradient Flow
OriginalA frosted hero backed by twin counter-rotating conic gradients, with flowing gradient text and an animated gradient-border stat card.

Spotlight Follow Background
OriginalA dot-grid section where a spring-eased spotlight follows the cursor and reveals a hidden lattice of coloured dots.

Dot Pattern Background
pattern.tsxA reusable animated background for React and Tailwind: dot pattern background.

Flickering Grid Background
grid.tsxA reusable animated background for React and Tailwind: flickering grid background.

Grid Pattern Background
pattern.tsxA reusable animated background for React and Tailwind: grid pattern background.

Retro Grid Background
grid.jsonA reusable animated background for React and Tailwind: retro grid background.

Spotlight Hero
OriginalA centred hero with a soft radial spotlight, badge and dual call-to-action.

Split Hero
OriginalA two-column hero pairing a headline and CTAs with a product mock and social proof.

Gradient Spotlight Hero
OriginalA minimal centred hero with a soft gradient-mesh backdrop, announcement pill and dual call-to-action buttons.

App Preview Hero
OriginalA centred hero that pairs headline copy with a realistic product dashboard mock built entirely from markup, complete with browser chrome and a floating notification card.

Waitlist Capture Hero
OriginalA dark, focused hero with an inline email capture form and avatar social proof, ready for pre-launch waitlists.

