Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Backgrounds

Pro

Reaction Diffusion Background for React

Turing patterns that grow behind your content: stripes, spots or coral spread from a few seeds and keep slowly rearranging. For React with Base UI, when a science, biotech or generative-art page needs a pattern that looks alive.

Framework

Reaction Diffusion simulates two chemicals spreading and reacting across a grid, the Gray-Scott model behind Turing patterns. One is fed in and consumed; the other feeds on it and decays. Out of a few seeds grow winding stripes, spots that split in two, or a coral-like network, and the pattern never quite freezes: the feed rate drifts slowly, so stripes reconnect and spots divide.

Use it for science, biotech and generative-art pages. For organic blobs that merge without a pattern, use Metaballs; for a cellular grid run by counting rules, Life; for a still cellular tessellation, Voronoi. It's a small canvas with one pixel per 8 px cell, which CSS scales up smoothly; an SVG filter then cuts the soft result at one level, so the shapes have crisp, smooth edges at any size. It costs a fraction of a millisecond a frame, redraws about 30 times a second and pauses when it scrolls out of view.

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

Reaction Diffusion is a container: give it a size, put your content inside, and the pattern grows behind it. For a background behind the whole page, pass className="fixed inset-0 -z-10" and no children.

Demos

Patterns

pattern picks the regime: "spots" (spots that split, like dividing cells), "maze" (the default, winding stripes) or "coral" (a branching network). These cards use cellSize={6}, the smallest, so even a small card holds several stripes.

Preview width

Color

color takes any CSS color, here gold on a bg-indigo-950 section, and intensity="strong" raises the pattern's opacity from the default 35% to 90%.

Preview width

Accessibility

The pattern is decoration: it's hidden from assistive tech and never takes the pointer. With reduced motion it grows a full pattern before the first paint, and again after a resize, and shows it, still. At the default intensity, "subtle", the pattern covers about half the area at 35% of its color, so headings in text-foreground read well over it; with "medium" or "strong", put copy on a plate (such as bg-background/80). Nothing flashes: the pattern changes by slow growth.

FAQ

What is Gray-Scott reaction-diffusion?

Two chemicals on a grid: U is fed in and consumed, V feeds on U and decays. Because they spread at different rates, random seeds turn into evenly spaced spots and stripes, the patterns Alan Turing proposed for animal coats in 1952.

How do I get spots instead of stripes?

Pass pattern="spots", "maze" or "coral". To explore further, feed and kill override the pattern's rates; small changes, around 0.002, are enough to change the kind of pattern, and some values make it die out.

How big is the pattern, and what does it cost?

cellSize sets both: 8 px by default, at least 6. A stripe is about 7 cells wide, and smaller cells mean more of them to simulate. The simulation runs 150 steps a second spread evenly over the frames, so at 1280 × 720 a frame takes about a quarter of a millisecond at 60 or 120 Hz, a larger screen never more than about 0.6 ms, and the canvas is redrawn only after every five steps.

Does it ever stop moving?

No. The feed rate drifts slowly up and down, so the pattern keeps reorganising instead of settling. speed scales how fast it evolves (150 simulation steps a second), and speed={0} holds it.

Can the pointer change the pattern?

With interactive, moving the pointer over the box drops seeds along its path, and they grow into the pattern around them; it shows best where the pattern is sparse. It's off by default, and touch never seeds.

Does it respect reduced motion?

Yes. It grows a pattern before the first paint and shows it as a still picture; nothing moves and the pointer does nothing.

API Reference

ReactionDiffusion

<div> data-slot="reaction-diffusion"

PropType
cellSize?number

A simulation cell's size in pixels, at least 6. It sets the pattern's scale (a stripe is about 7 cells wide) and its cost.

Default
8
color?string

The pattern's color, any CSS color, fading to transparent. @default "var(--primary)".

feed?number

Overrides the pattern's feed rate F; a change of 0.002 can change the kind of pattern.

intensity?"subtle" | "medium" | "strong"

How strongly the pattern shows: its opacity, 35%, 60% or 90%. @default "subtle".

Type
"subtle" | "medium" | "strong"
Default
"subtle"
interactive?boolean

Whether the pointer seeds new growth where it moves (never on touch). @default false.

Default
false
kill?number

Overrides the pattern's kill rate k.

pattern?"coral" | "maze" | "spots"

The kind of pattern: winding stripes, spots that split, or a coral network. @default "maze".

Type
"coral" | "maze" | "spots"
Default
"maze"
speed?number

Multiplies the pace of 150 simulation steps a second; 0 holds the pattern. @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
--reaction-diffusion-colorstring

The pattern's color (the theme's --primary).

--reaction-diffusion-edgestring
All 100 backgrounds