Skewed Grid
A free tilted grid background with ragged rails for structural product sections.
Infrastructure
Built on a grid you can feel
A tilted lattice with ragged rails running off toward the sections above and below. The silhouette is pinned to a seed, so the same layout renders on the server and in the browser every time.
Customise
Code
<BgSkewedGrid />Skewed Grid is a free animated grid background React component for Next.js, React, and Tailwind. It renders a solid body of cells with rails running outward from each edge on a seeded walk, then rotates and tilts the whole lattice in 3D so it reads as architecture rather than wallpaper.
Cell size, body size, rail depth per edge, rotation, tilt, perspective, fill density, and the cursor response all change the real effect. The layout is pinned to a seed, so the same markup renders on the server and in the browser, and the full grid stays visible without JavaScript and when reduced motion is enabled.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/bg-skewed-gridUsage
import { BgSkewedGrid } from "@/components/bg-skewed-grid";
export function Example() {
return (
<section className="relative overflow-hidden">
<BgSkewedGrid
cell={30}
cols={20}
rows={13}
edgeTop={4}
edgeBottom={7}
edgeLeft={10}
rotate={-30}
tiltX={30}
seed={20250728}
/>
<div className="relative">
<h2 className="text-4xl font-semibold">Your content here</h2>
<p className="text-muted-foreground">The lattice sits behind it.</p>
</div>
</section>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| cell | number | 30 | Size of one cell in px, rounded and clamped to 16 to 64. |
| cols | number | 20 | Columns in the solid body before rails, clamped to 4 to 36. |
| rows | number | 13 | Rows in the solid body before rails, clamped to 3 to 26. |
| edgeTop | number | 4 | Cells columns may extend above the body, clamped to 0 to 16. 0 gives a clean straight edge. |
| edgeRight | number | 0 | Cells rows may extend right of the body, clamped to 0 to 16. |
| edgeBottom | number | 7 | Cells columns may extend below the body, clamped to 0 to 16. |
| edgeLeft | number | 10 | Cells rows may extend left of the body, clamped to 0 to 16. |
| rotate | number | -30 | In-plane rotation in degrees, clamped to -45 to 45. |
| tiltX | number | 30 | Tilt away from the viewer in degrees, applied after the rotation, clamped to -45 to 45. |
| perspective | number | 1100 | Camera distance for the tilt in px, clamped to 400 to 2400. |
| skewX | number | 0 | Horizontal cell shear in degrees, clamped to -25 to 25. 0 keeps cells square and emits no skew. |
| skewY | number | 0 | Vertical cell shear in degrees, clamped to -25 to 25. |
| fillRate | number | 0.06 | Chance each visible cell takes a solid fill, clamped to 0 to 0.15. |
| accentShare | number | 0.12 | Of the filled cells, the share taking the accent colour, clamped to 0 to 1. |
| seed | number | 20250728 | Pins the silhouette and fills. The same seed always produces the same layout, on the server and the client. |
| mask | "none" | "radial" | "linear" | "none" | How the grid dissolves at its edges. none shows the full ragged silhouette. |
| maskAngle | number | 225 | Direction of the linear fade in degrees, clamped to 0 to 360. |
| maskOpacity | number | 0 | Strength of the mask tint, clamped to 0 to 1. At 0 the fade is pure alpha. |
| hoverIn | number | 0.08 | Seconds for a cell to light on hover, clamped to 0.02 to 0.5. |
| trailOut | number | 1.2 | Seconds for a cell to fade after the cursor leaves, clamped to 0.1 to 3. Longer values leave a visible trail. |
| wakeShift | number | 2 | Resting downward offset in px, settling to 0 on hover, clamped to 0 to 10. |
| glowRadius | number | 150 | Radius of the cursor glow in px, clamped to 60 to 340. |
| lineOpacity | number | 0.08 | Grid line alpha, clamped to 0 to 1. |
| fillOpacity | number | 0.05 | Neutral cell fill alpha, clamped to 0 to 1. |
| accentOpacity | number | 0.16 | Accent cell fill alpha, clamped to 0 to 1. |
| hoverOpacity | number | 0.28 | Strength of the hovered cell, clamped to 0 to 1. |
| glowOpacity | number | 0.14 | Strength of the cursor glow, clamped to 0 to 1. |
| lineWidth | number | 1 | Grid line thickness in px, clamped to 0.5 to 3. |
| canvasColor | string | undefined | Background painted behind the grid. Falls back to the --skewed-grid-canvas token. |
| lineColor | string | undefined | Grid line colour for this instance. Falls back to the --skewed-grid-line token. Any CSS colour is accepted; lineOpacity is applied to it. |
| fillColor | string | undefined | Neutral cell fill colour. Falls back to the --skewed-grid-fill token, with fillOpacity applied. |
| accentColor | string | undefined | Accent cell fill colour. Falls back to the --skewed-grid-accent token, with accentOpacity applied. |
| hoverColor | string | undefined | Colour of the cell under the cursor. Falls back to the --skewed-grid-hover token, with hoverOpacity applied. |
| glowColor | string | undefined | Colour of the pool following the cursor. Falls back to the --skewed-grid-glow token, with glowOpacity applied. |
| maskColor | string | undefined | Tint the grid fades into. Falls back to the --skewed-grid-mask token, with maskOpacity applied. |
| className | string | undefined | Additional classes merged onto the absolute fill root. |
Customisation
Skewed Grid exposes seven component tokens, one per colour channel. Each falls back to a semantic token, and every one can also be overridden per instance with the matching colour prop. Alpha stays on the separate opacity props, so a token only ever carries a colour:
:root {
--skewed-grid-canvas: var(--background);
--skewed-grid-line: var(--foreground);
--skewed-grid-fill: var(--foreground);
--skewed-grid-accent: var(--primary);
--skewed-grid-hover: var(--primary);
--skewed-grid-glow: var(--primary);
--skewed-grid-mask: var(--background);
}Frequently asked questions
- Is Skewed Grid free for commercial use?
- Yes. Skewed Grid is MIT licensed, so you can use it in personal and commercial projects without attribution.
- How does Skewed Grid handle performance and accessibility?
- The grid is plain CSS with no animation library and no JavaScript layout work: cells are built once during render from the seed, and the cursor glow is two custom properties written on pointer move, so moving the cursor never re-renders React. The layer is decorative and aria-hidden, it never takes focus, and hover work is gated on a fine pointer. When reduced motion is enabled the grid renders in full with no wake, trail, or glow.
- Why does the same seed matter?
- The silhouette and the scattered fills come from a seeded generator rather than Math.random, so the server and the browser produce identical markup. Change the seed for a different layout; keep it to pin the one you chose.
- Can I change the colours and geometry?
- Use the seven CSS custom properties to retheme every instance at once, or the colour props for a single instance. Use the component props or the live playground for cell size, body size, rail depth per edge, rotation, tilt, perspective, fill density, and the cursor response.