Skip to content
Template Empire
Browse components

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

30px
1px
20
13
-30deg
30deg
1100px
0deg
0deg
4 cells
0 cells
7 cells
10 cells
0.06
0.12
20250728
0.08s
1.2s
2px
150px
0.08
0.05
0.16
0.28
0.14
225deg
0

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-grid

Usage

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

PropTypeDefaultDescription
cellnumber30Size of one cell in px, rounded and clamped to 16 to 64.
colsnumber20Columns in the solid body before rails, clamped to 4 to 36.
rowsnumber13Rows in the solid body before rails, clamped to 3 to 26.
edgeTopnumber4Cells columns may extend above the body, clamped to 0 to 16. 0 gives a clean straight edge.
edgeRightnumber0Cells rows may extend right of the body, clamped to 0 to 16.
edgeBottomnumber7Cells columns may extend below the body, clamped to 0 to 16.
edgeLeftnumber10Cells rows may extend left of the body, clamped to 0 to 16.
rotatenumber-30In-plane rotation in degrees, clamped to -45 to 45.
tiltXnumber30Tilt away from the viewer in degrees, applied after the rotation, clamped to -45 to 45.
perspectivenumber1100Camera distance for the tilt in px, clamped to 400 to 2400.
skewXnumber0Horizontal cell shear in degrees, clamped to -25 to 25. 0 keeps cells square and emits no skew.
skewYnumber0Vertical cell shear in degrees, clamped to -25 to 25.
fillRatenumber0.06Chance each visible cell takes a solid fill, clamped to 0 to 0.15.
accentSharenumber0.12Of the filled cells, the share taking the accent colour, clamped to 0 to 1.
seednumber20250728Pins 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.
maskAnglenumber225Direction of the linear fade in degrees, clamped to 0 to 360.
maskOpacitynumber0Strength of the mask tint, clamped to 0 to 1. At 0 the fade is pure alpha.
hoverInnumber0.08Seconds for a cell to light on hover, clamped to 0.02 to 0.5.
trailOutnumber1.2Seconds for a cell to fade after the cursor leaves, clamped to 0.1 to 3. Longer values leave a visible trail.
wakeShiftnumber2Resting downward offset in px, settling to 0 on hover, clamped to 0 to 10.
glowRadiusnumber150Radius of the cursor glow in px, clamped to 60 to 340.
lineOpacitynumber0.08Grid line alpha, clamped to 0 to 1.
fillOpacitynumber0.05Neutral cell fill alpha, clamped to 0 to 1.
accentOpacitynumber0.16Accent cell fill alpha, clamped to 0 to 1.
hoverOpacitynumber0.28Strength of the hovered cell, clamped to 0 to 1.
glowOpacitynumber0.14Strength of the cursor glow, clamped to 0 to 1.
lineWidthnumber1Grid line thickness in px, clamped to 0.5 to 3.
canvasColorstringundefinedBackground painted behind the grid. Falls back to the --skewed-grid-canvas token.
lineColorstringundefinedGrid line colour for this instance. Falls back to the --skewed-grid-line token. Any CSS colour is accepted; lineOpacity is applied to it.
fillColorstringundefinedNeutral cell fill colour. Falls back to the --skewed-grid-fill token, with fillOpacity applied.
accentColorstringundefinedAccent cell fill colour. Falls back to the --skewed-grid-accent token, with accentOpacity applied.
hoverColorstringundefinedColour of the cell under the cursor. Falls back to the --skewed-grid-hover token, with hoverOpacity applied.
glowColorstringundefinedColour of the pool following the cursor. Falls back to the --skewed-grid-glow token, with glowOpacity applied.
maskColorstringundefinedTint the grid fades into. Falls back to the --skewed-grid-mask token, with maskOpacity applied.
classNamestringundefinedAdditional 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.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates