Spacetime grid
Getting started
Install the spacetime grid and put it behind your page.
-
Install the package and three.js:
pnpm add @abhiramkrishna/spacetime-grid threenpm install @abhiramkrishna/spacetime-grid threeyarn add @abhiramkrishna/spacetime-grid threebun add @abhiramkrishna/spacetime-grid threethreeis a peer dependency (version 0.160 or later), so the grid uses your app’s copy. -
Add an element for the grid to fill, and give it a size. For a full-page background:
CSS .background { position: fixed; inset: 0; z-index: -1; } -
Create the grid:
TypeScript import { SpacetimeGrid } from "@abhiramkrishna/spacetime-grid"; const grid = new SpacetimeGrid(document.querySelector(".background")!);Vue <script setup lang="ts"> import { SpacetimeGrid } from "@abhiramkrishna/spacetime-grid/vue"; </script> <template> <div class="background"><SpacetimeGrid /></div> </template>TSX import { SpacetimeGrid } from "@abhiramkrishna/spacetime-grid/react"; export function Background() { return <div className="background"><SpacetimeGrid /></div>; }TypeScript import { defineSpacetimeGridElement } from "@abhiramkrishna/spacetime-grid/element"; defineSpacetimeGridElement();HTML <spacetime-grid class="background"></spacetime-grid> -
Match the fog to your background colour, so tiles fade into the page instead of ending at a hard edge:
TypeScript new SpacetimeGrid(el, { theme: { fog: "#011627" } });
How it fits on the page
- Size: the grid adds a
<canvas>that fills its element and follows its size. You can also pass a<canvas>you already have. - Input: the cursor and clicks are tracked on
window, so the grid still reacts when it sits behind your content withz-index: -1. Positions are mapped onto the canvas, and anything outside it is ignored. - Phone layout: below 1024px of canvas width (
compactBreakpoint), the grid drops lower and shrinks a little, which suits phones.
Changing it while it runs
grid.setOptions({ waveAmplitude: 0.15, wellRadius: 3 });
grid.setTheme({ hover: "#5ee6ff" });
grid.ripple(window.innerWidth / 2, window.innerHeight / 2);Most options change live. cols, rows, cellSize and fill set the size of the tile mesh, so changing them means creating a new grid; the framework wrappers do that for you. See Options for the full list.
Cleaning up
grid.destroy();destroy() stops the loop, removes the listeners and frees the GPU resources. The wrappers call it when they unmount.
Reduced motion
Visitors with prefers-reduced-motion: reduce get a single still frame of the grid, with no waves, well or ripples. If they change the setting while the page is open, the grid switches over. Set reducedMotion: "always" or "never" to override this.