Backgrounds
Retro Grid
A regular grid rotated in 3D, so perspective does the vanishing point for free, under a slit sun.
Original by Plinth · MIT
Report a problem or suggest an improvementInstall
npx shadcn@latest add https://plinthui.com/r/retro-grid.json// 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>
</>
);
}