Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Labyrinth Background for React

A seeded maze behind your content, with a few lights exploring its corridors, lighting the walls around them and turning back at dead ends. For React with Base UI, when a puzzle, game or security page should feel like it's solving something.

Framework

A seeded maze fills the box, its walls at a soft 40% and fading toward the edges, while a few lights explore its corridors from the middle outward: each trails a short tail, lights up the walls around it as it passes, runs into side corridors and turns back at dead ends. The maze is carved when the page renders and repeats with no visible seam on wide screens; the walls are one still masked layer, the lights are small dots moved from cell to cell by translate keyframes the install adds to your stylesheet, and their glow shows through a second copy of the maze's mask, so only the nearby walls catch it. Nothing repaints and no script runs.

Use it for puzzle, game or security pages. For a board of traces with signals, use Circuit; for lights racing along an open grid, Laser Grid; for cells that evolve on a grid, Life.

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Usage

import { Labyrinth } from "@/components/ui/labyrinth";

Labyrinth is a container: give it a size and put your content inside. The maze sits behind the content and the box clips it.

<Labyrinth className="flex min-h-[420px] items-center justify-center">
  <h1 className="text-5xl font-semibold">Find the way through</h1>
</Labyrinth>

For a backdrop behind the whole page, leave it empty and fix it under everything else:

<Labyrinth className="fixed inset-0 -z-10" />

Demos

Theme colours

By default the maze keeps its signature neon: indigo walls and cyan lights, a deeper cyan on light themes. Here wallColor and lightColor take your theme's colours instead: faint walls in the foreground and lights in the primary colour.

Preview width

Tighter maze

A denser maze in a dark card: cellSize={24}, count={8} lights and speed={1.5}. On a dark surface in a light theme, pass the pale cyan as lightColor so the lights stay bright.

Preview width

Accessibility

The maze is decorative: it's hidden from screen readers and lets every click through to your content. With reduced motion the lights stop where they are, a still picture of the maze with a few lit corners. Nothing flashes: the lights glide a cell at a time and the walls brighten and fade as they pass. The walls show at 40% and fade toward the edges, but they still cross under every letter, so keep copy in your foreground colour, put a softly faded panel behind long text or pass a fainter wallColor (about 25% of your foreground); avoid backdrop-blur, which would re-blur the moving lights on every frame.

FAQ

Is the maze different on every visit?

No: it's carved from seed when the page renders, so the server and the browser draw the same maze. Change seed for another one.

What are the lights doing?

Each follows the corridors around its start for 30 steps, on into side corridors and back out of dead ends, the way the maze was carved; then it retraces its way home and starts again, so it never jumps. Its tail is eight fainter dots a fraction of a step behind it, and its glow lights only the walls, through the maze's own mask.

How do I make the maze denser?

Lower cellSize (40 by default); the walls stay 1.5px at any size. count and speed set how many lights explore and how fast.

Why does a small card show fewer lights?

The lights walk the maze's own corridors, so they start from fixed places around the centre: the first ones close to it, the rest over up to 1280×720. count is about how many explore a 1440×900 box; a small card shows a couple.

Can I use my theme's colours instead of neon?

Yes: pass wallColor and lightColor, as in "Theme colours", or set --labyrinth-wall-color and --labyrinth-light-color from your own CSS.

Does it slow the page?

No script runs and nothing repaints: the walls are one still masked layer, and the lights are small dots that only change translate, which the browser composites. Offscreen, it isn't painted.

What happens with reduced motion?

The lights stop where they are, so the maze shows a few still lights with their walls lit.

API Reference

Labyrinth

<div> data-slot="labyrinth"

PropType
cellSize?number

The side of one maze cell, in pixels; walls stay 1.5px. @default 40.

Default
40
count?number

About how many lights explore a 1440×900 box. They walk the maze's own corridors from around the centre, over at most 1280×720 (where a radial fade keeps the maze): a small card shows a couple.

Default
5
lightColor?string

The lights' colour, any CSS colour: their heads, their tails and the walls they light around them.

Default
a neon cyan, deeper on light themes
seed?number

Another maze: each whole number carves a different one and sends the lights on different tours.

Default
0
speed?number

How fast the lights move, as a multiplier: 1 is a cell every 380ms.

Default
1
wallColor?string

The walls' colour, any CSS colour. @default a neon indigo at 40%.

render?ReactElement | ((props: object, state: object) => ReactElement)

Replace the host element or compose it with another component.

Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string

Merged with the part's classes.

CSS variableType
--labyrinth-light-colorstring

The lights' colour (a neon cyan).

--labyrinth-speedstring

How fast the lights move, a multiplier (1).

--labyrinth-wall-colorstring

The walls' colour (a neon indigo at 40%).

All 100 backgrounds