shadcn.io is not affiliated with official shadcn/ui
Orb Grid Shader draws three soft orbs, indigo, pink and amber, drifting slowly under a fine square grid. Each orb is also a gravity well: the grid pinches toward it like a spacetime diagram, and its lines and crossings take the orb's colour where it passes beneath, fading to a faint hairline everywhere else. A WGSL fragment shader on WebGPU computes every pixel each frame, so the lines stay one CSS pixel wide and sharp at any size, for about a tenth of a millisecond of GPU time a frame.
Use it behind a product launch, an AI or startup hero, a pricing section or a changelog header. For a flat grid in plain CSS, use the Grid Pattern background; for colour without structure, Mesh Gradient or Gradient Mesh Shader; for a sheet of dots instead of lines, Breathing Dots Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows a CSS grid over the same glows in browsers without WebGPU.
Installation
Usage
import { OrbGridShader } from "@/components/ui/orb-grid-shader";<OrbGridShader className="flex min-h-[32rem] items-center justify-center">
<h1 className="text-5xl font-semibold text-white">Launch week</h1>
</OrbGridShader>Orb Grid Shader is a container: your content sits on top of the grid, in normal flow. It fills its own box, so give it a height or content. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10". The page is near-black in both color schemes, so put white or light text over it.
The colors take any CSS color and follow a theme switch, so orbAColor="var(--primary)" ties the first orb to your brand. lineColor sets the hairlines and their highlights, and backgroundColor the page behind them.
Demos
Flat grid
warp={0} turns the wells off, so the grid stays square and only the colour moves: calmer behind a pricing table or dense copy. cellSize={48} opens the grid up, and intensity={0.7} dims the orbs.
Interactive, in a card
With interactive, the pointer is one more small well: the grid dimples toward it and its lines brighten as it moves over the card. The well eases after the pointer, and fades out when the pointer leaves, so the grid relaxes. Touch doesn't move it. Here the orbs are cyan, indigo and violet.
Performance
About 0.13 ms of GPU time a frame at 1280×720 on an M2 Max laptop; slower GPUs take several times longer. It's one of the lightest shaders, so it keeps quality={1}: the hairlines would blur at half resolution. The animation stops when the shader scrolls out of view, and the browser pauses it in a hidden tab. Every shader on a page shares one GPU device and one frame loop, and vgpu (about 50 KB gzipped) loads only when the first one mounts.
Browser support
The shader needs WebGPU: Chrome and Edge, Safari 26 and later, and Firefox on Windows and macOS. Elsewhere, and until the first frame, the box shows a CSS grid over three soft glows of the same colors, so the layout never jumps. data-state on the root reads unsupported there, if you want to style around it. See Shader Canvas.
Accessibility
The grid is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame and stops. Nothing flashes: the orbs drift over tens of seconds. At the default colors, white text stays above 8:1 on 95% of the box and above 12:1 on three quarters of it; only the brightest crossings at the heart of each orb come close to white, so keep small body text off the orbs' centres, especially at intensity above 1.
FAQ
Can I use my brand colors?
Yes. orbAColor, orbBColor and orbCColor set the three orbs, lineColor the hairlines and backgroundColor the page. Each takes any CSS color and follows a theme switch, so orbAColor="var(--primary)" works. Keep the background dark: the orbs add light to it, and on a light page they'd wash out.
How does the grid bend?
Each orb is a gravity well. Near it, the shader reads the grid from a little further out, so the lines bunch together and curve toward the orb, as in a spacetime diagram. warp sets how hard the wells pull, from 0 (a flat grid) to 2; one well alone never folds the grid over itself.
Does cellSize stay the same on a retina screen?
Yes. cellSize is in CSS pixels, from 16 to 96, and the lines are one CSS pixel wide, at any screen ratio and any quality. Lines are anti-aliased, so they stay crisp as they bend.
Can the grid react to the pointer?
Set interactive and the pointer becomes a small fourth well that dimples the grid and brightens the lines under it. It eases after the pointer, fades in as it comes over the box and fades out when it leaves; touch is ignored, so scrolling on a phone never drags it. Without interactive there's no fourth well.
API Reference
OrbGridShader
data-slot="orb-grid-shader"
backgroundColor?string
The page behind the orbs and the grid. Any CSS colour. @default "#09090b".
- Default
"#09090b"
cellSize?number
The grid's square cells, in CSS pixels, from 16 to 96. @default 32.
- Default
32
fallback?string
What shows until the first frame and in browsers without WebGPU: a CSS
background value (gradients, sizes, a colour) that looks like the
shader. It can use the colour props' --shader-<field> variables.
intensity?number
How bright the orbs glow, from 0 (a bare grid) to 2. @default 1.
- Default
1
interactive?boolean
Whether u.pointer follows the pointer. @default false.
- Default
false
lineColor?string
The grid's hairlines away from the orbs, and their highlights. Any CSS colour. @default "#ffffff".
- Default
"#ffffff"
orbAColor?string
The first orb, which starts upper left. Any CSS colour. @default "#6366f1".
- Default
"#6366f1"
orbBColor?string
The second orb, which starts right of centre. Any CSS colour. @default "#ec4899".
- Default
"#ec4899"
orbCColor?string
The third orb, which starts at the bottom. Any CSS colour. @default "#f59e0b".
- Default
"#f59e0b"
paused?boolean
Holds the current frame. @default false.
quality?number
Render scale, from 0.25 to 1, of the screen's pixels (capped at 2×). @default 1.
speed?number
Animation speed: 1 is normal, 0 holds the frame. @default 1.
time?number
A fixed moment, in seconds: draws it and doesn't animate.
warp?number
How hard the orbs pull the grid in, from 0 (flat) to 2. @default 1.
- Default
1
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
Forwarded to the part.
Related
- Pro


Breathing Dots Shader
GeometryA sheet of dots instead of lines


Gradient Mesh Shader
Flow & gradientsColor without structure, free


Fluted Glass Shader
Light & glassSoft color behind reeded glass, free
- Pro


Triangle Mesh Incircles Shader
Patterns & tilingsPlayful geometry in ink on paper


Shader Canvas
CanvasYour own WGSL on the same canvas, free


Dither Gradient Shader
Digital & retroDrifting orbs, dithered on paper, free