Skip to content
Plinth

Backgrounds

Retro Grid

A regular grid rotated in 3D, so perspective does the vanishing point for free, under a slit sun.

#background#retro#grid#perspective#synthwave

Install

npx shadcn@latest add https://plinthui.com/r/retro-grid.json
Open in v0
// No hooks or handlers, so this stays a server component — it is pure CSS.
// 3D transforms, masks and keyframes are outside what Tailwind can express.
const css = `
.retro {
  position: relative;
  min-height: 300px;
  overflow: hidden;
  background: linear-gradient(180deg, #17082e 0%, #2b0f3d 42%, #08030f 100%);
  /* The plane is rotated in 3D, so the container needs the perspective. */
  perspective: 240px;
  isolation: isolate;
}

/* One rotated element with a repeating gradient, not N lines. Perspective
   does the convergence for free — drawing lines that meet at a vanishing
   point by hand means computing every spacing. */
.retro__plane {
  position: absolute;
  left: -50%;
  bottom: -12%;
  width: 200%;
  height: 72%;
  transform: rotateX(72deg);
  transform-origin: 50% 100%;
  background:
    repeating-linear-gradient(90deg, rgba(255, 90, 190, 0.55) 0 1.5px, transparent 1.5px 56px),
    repeating-linear-gradient(0deg, rgba(120, 220, 255, 0.45) 0 1.5px, transparent 1.5px 56px);
  /* Scrolling the horizontal lines by exactly one cell makes the loop
     seamless: the grid ends up identical to where it started. */
  animation: retro-run 2.6s linear infinite;
}

.retro__sun {
  position: absolute;
  left: 50%;
  top: 16%;
  width: 140px;
  height: 140px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: linear-gradient(180deg, #ffd76e 0%, #ff7a6e 52%, #c8408f 100%);
  /* Horizontal slits cut through the lower half, the way the sun is drawn in
     this style — a mask rather than stacked bars, so it stays one element. */
  -webkit-mask: repeating-linear-gradient(0deg, #000 0 7px, transparent 7px 12px), linear-gradient(180deg, #000 42%, transparent 42%);
  -webkit-mask-composite: source-out;
  mask: repeating-linear-gradient(0deg, #000 0 7px, transparent 7px 12px), linear-gradient(180deg, #000 42%, transparent 42%);
  mask-composite: exclude;
  filter: drop-shadow(0 0 26px rgba(255, 122, 110, 0.5));
}

/* Fades the horizon so the grid does not end in a hard line. */
.retro__fade {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, transparent 46%, rgba(8, 3, 15, 0.72) 76%, #08030f 100%);
  pointer-events: none;
}

@keyframes retro-run {
  to { background-position: 0 0, 0 56px; }
}

@media (prefers-reduced-motion: reduce) {
  .retro__plane { animation: none; }
}
`;

export function RetroGrid() {
  return (
    <>
      <style>{css}</style>
      <div className="retro">
        <div className="retro__plane" />
        <div className="retro__sun" />
        <div className="retro__fade" />
      </div>
    </>
  );
}

More in Backgrounds

Similar tags