Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Resonance Background for React

Grains of sand gather on the still lines of a vibrating plate, and the figure slowly morphs as the vibration drifts. For React with Base UI, when a science, audio or research page should show physics at work.

Framework

Resonance recreates Chladni's 1787 experiment: sand on a vibrating plate collects along the lines that stay still, drawing curves, loops and crossings. The two numbers that set the vibration drift slowly, so the lines bend, split and rejoin, and the grains migrate over to the new ones. It's drawn in your text color, so it reads as black sand on white in a light theme and white sand on black in a dark one.

Use it for science, acoustics, audio and research pages. For wave fringes from two sources instead of particles, use Interference; for nested contour lines, Topography; for free-floating dust, Particles. About 1,600 grains in a 1280×720 box each take a small random step 60 times a second and keep it only if it brings them nearer a still line; it's one small canvas that pauses when it scrolls out of view, and on a 120 Hz display it draws only when the sand has moved.

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 { Resonance } from "@/components/ui/resonance";
<Resonance className="min-h-[480px]">
  <h1 className="text-5xl font-semibold">Ship faster</h1>
</Resonance>

Resonance is a container: give it a size, put your content inside, and the sand sits behind it. The plate is a square as wide as the box's longer side, so figures keep their shape on wide and tall boxes. For a background behind the whole page, pass className="fixed inset-0 -z-10" and no children.

Demos

Brush

speed={0} holds one figure, and interactive lets the pointer brush the sand aside. Sweep through a line and the grains find their way back to it.

Preview width

Dense

count={4000} and jitter={0.6} (smaller steps) draw crisper, fuller lines; color puts them in the theme's primary color.

Preview width

Accessibility

The sand is decoration: it's hidden from assistive tech and never takes the pointer, unless you turn on interactive, and then only on its own box and never on touch. With reduced motion it lets the sand settle before the first paint and shows that figure, still. Grains are 1.4 px and lines are thin, so text in text-foreground stays readable on top. Nothing flashes: the figure changes over tens of seconds.

FAQ

What is a Chladni figure?

The pattern sand forms on a vibrating plate. Most of the plate moves up and down, but along certain lines, the nodal lines, it stays still, and the sand bounced off everywhere else comes to rest there. Ernst Chladni drew them with a violin bow in 1787.

Why does the figure change?

The plate vibrates in two modes whose numbers drift slowly, so the still lines bend, split and rejoin, and the grains move over to the new ones. speed scales the drift; speed={0} holds one figure while the grains keep settling.

How do I make the lines sharper or looser?

Lower jitter gives tighter lines (smaller steps), higher gives looser, livelier ones. A higher count makes them fuller: it's the grains in a 1440×900 box (1,900 by default). The figure's lines grow with the box's side, so other sizes get grains in proportion to the square root of their area, which keeps the lines equally dense in a card or a full page, up to 6,000.

Can the pointer move the sand?

With interactive, the pointer pushes grains within 60 px aside, and they settle back onto the lines once it leaves. It's off by default, and touch never pushes.

Will it run on phones?

Yes. The sand steps 60 times a second whatever the display's refresh rate, so a 120 Hz screen costs no more than a 60 Hz one; a step of about 1,600 grains takes a fraction of a millisecond, the random draws and their directions come from tables made once, and the loop stops when the plate scrolls out of view.

Does it respect reduced motion?

Yes. The sand settles before the first paint and that figure stays, still; it's redrawn as it was after a resize.

API Reference

Resonance

<div> data-slot="resonance"

PropType
color?string

The grains' color, any CSS color. @default "var(--foreground)".

count?number

How many grains of sand in a 1440×900 box. The figure's lines grow with the box's side, so other sizes get grains in proportion to the square root of their area (enough for the same dense lines), never more than 6,000.

Default
1900
interactive?boolean

Whether the pointer brushes the sand aside; it settles again after. Never on touch. @default false.

Default
false
jitter?number

Each grain's step size: lower draws tighter lines, higher looser ones. @default 1.

Default
1
speed?number

How fast the figure changes; 0 holds one figure (the grains still settle). @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

Merged with the part's classes.

CSS variableType
--resonance-colorstring

The grains' color (the text color, --foreground).

All 100 backgrounds