Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Shaders

Pro

Mandelbrot Pattern Decoration Shader for React

A valley of the Mandelbrot set whose bands are glazed like folk-art ceramics, set with beads and lozenges, under a dark sky laced with blue filaments. For React with Base UI, when an art, culture or creative page wants ornament with infinite depth.

Framework

Mandelbrot Pattern Decoration Shader looks into the valley where curled, trunk-like spirals line the edge of the Mandelbrot set. The bands around it, one for each step a point takes to escape, are glazed like painted tiles in cobalt, ivory, turquoise and gold, each with its own motif: rings, lozenges with gold studs, or rows of pips, edged with a gold rim and a dark seam. Near the set they thin into blue lace, and above it the set's inside is a dark sky with a faint glow along its edge. The view sways slowly, breathing in and out, and the beads slide along their bands. A WGSL fragment shader on WebGPU iterates z → z² + c up to 128 times per pixel and lays each motif out in the coordinates where the orbit escapes, so it follows every curl of the bands.

Use it behind an art, culture, music or creative-studio page, or a print shop that wants a pattern with depth. For an endless zoom into fern-like fronds in plain CSS, use the Fractal background; for another infinite geometry, the hyperbolic tiles of Poincaré Disc Animation Shader. It runs only while it's on screen, holds a still frame with reduced motion, and shows CSS stripes under a dark sky in browsers without WebGPU.

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 {
  MandelbrotPatternDecorationShader,
} from "@/components/ui/mandelbrot-pattern-decoration-shader";
<MandelbrotPatternDecorationShader className="flex min-h-[32rem] justify-center pt-24">
  <h1 className="text-5xl font-semibold text-white">Ship faster</h1>
</MandelbrotPatternDecorationShader>

Mandelbrot Pattern Decoration Shader is a container: your content sits on top of the pattern, 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 decorated bands run along the bottom 40% of the box and the dark sky fills the rest, so set white or light text near the top, as above.

Demos

Big beads

dotScale={1.6} enlarges the rings, lozenges and pips, and iterations={64} stops each pixel after 64 steps: the lace near the set thins out, and it costs the GPU less.

Preview width

In a card

zoom={2.5} moves in on the spirals, so a card shows a few of them large, like an art print, and gloss={1.6} strengthens the glaze's sheen.

Preview width

Performance

About 0.7 ms of GPU time a frame at 1280×720 on an M2 Max laptop at the defaults, 0.5 ms with iterations={64}, and about 1 ms at zoom={4}, where more of the view is close to the set; slower GPUs take several times longer. The set's main body is recognized by a formula and skipped, so the dark sky costs almost nothing. It keeps full quality: the motifs are crisp shapes that 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 dark sky over stripes of cobalt, ivory, turquoise and gold, 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 pattern 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 view breathes over about 33 seconds, and the beads slide slowly. White text reads very well on the sky: across the renders it keeps above 18:1 contrast over the top half of the box. Keep text off the bands, where it drops to about 2:1 on the ivory and gold.

FAQ

How is the Mandelbrot set computed?

Each pixel stands for a complex number c. Starting from zero, the shader repeats z → z² + c, up to 128 times. If z flies off past a large radius, the point is outside the set, and the number of steps it took picks its band; if it never does, the point is inside, and draws as the dark sky.

Where do the beads and lozenges come from?

From the point where each orbit escapes. Its angle and the logarithm of its size make a grid of square cells that follows the bands exactly, curls included, and each band draws one motif in those cells. Because the grid comes from the math, the beads shrink and turn with the bands without any distortion.

How many iterations does it use?

128 at most, set by iterations from 32 to 128. More steps resolve the fine lace close to the set; fewer are faster and leave the lace thinner, while the big decorated bands, which escape within a few steps, look the same.

Can I zoom anywhere?

zoom moves in on the same valley, from 0.5 to 4, and the view keeps breathing around it. The region itself is fixed: 32-bit GPU math runs out of precision on much deeper zooms, and this valley is where the decoration reads best.

How do I change the look of the bands?

dotScale sizes the motifs, from 0.5 to 2, gloss sets the glaze's sheen from 0 (matte) to 2, and brightness scales the whole picture from 0.5 to 1.5. The palette, cobalt, ivory, turquoise and gold, is the shader's signature.

Will it slow my page down?

It costs about 0.7 ms of GPU time a frame at 1280×720 on a laptop, and the CPU only sets a few numbers each frame. It stops when it's off screen. On a slow GPU, lower iterations first: 64 takes about 0.5 ms and keeps the bands.

Credits

Inspired by a decorated Mandelbrot pattern (opens in a new tab) by Shane on Shadertoy. This is a new shader written from a description of the look, not a port: the region of the set, the square log-polar cells, the motifs, the ceramic palette and glaze, the sky and the code are ours. The escape-time iteration, its distance estimate and the main-cardioid test are textbook Mandelbrot math.

API Reference

MandelbrotPatternDecorationShader

data-slot="mandelbrot-pattern-decoration-shader"

PropType
brightness?number

Overall brightness, from 0.5 to 1.5. @default 1.

Default
1
dotScale?number

The size of the beads and lozenges in each band, from 0.5 to 2. @default 1.

Default
1
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.

gloss?number

The glaze's sheen across the bands, from 0 (matte) to 2. @default 1.

Default
1
interactive?boolean

Whether u.pointer follows the pointer. @default false.

iterations?number

The most steps each pixel takes, from 32 to 128: fewer is faster and leaves less lace. @default 128.

Default
128
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.

zoom?number

How far in the view starts, from 0.5 to 4. @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.

All 101 shaders