Surface study no. 04
A studio for identities that move. We cast brands in liquid metal, then let them settle into something you can hold.
A live WebGL paint pour: a ramp of up to six colors, blended in Oklab, runs through layered fractal noise that warps itself twice, so the colors fold into marbled, swirling streams that drift slowly along a set direction like paint poured and gently stirred. Fine streaks run inside the streams, a soft gloss catches the folds and a film grain sits on top. Colors, scale, warp, detail, flow direction, stretch, ramp repeats, speed, contrast, sheen, saturation, grain amount and size, the seed and the cursor pull are all props; a new palette fades through over a set time, and the paint bends softly toward the cursor like a lens. It unfolds softly out of its first color on load, adapts its resolution to the device, pauses offscreen, holds a still frame for reduced motion and falls back to a plain CSS ramp without WebGL.
The import and the props worth knowing about, in one place.
import { FluidGradient } from "@/components/beste/component/fluid-gradient";
// As a layer behind content
<section className="relative min-h-[40rem]">
<FluidGradient className="absolute inset-0" />
<div className="relative">...</div>
</section>
// Long, bold streams of sunset colors flowing upward
<FluidGradient
className="min-h-[32rem]"
colors={["#2a0f3d", "#c2185b", "#ff8a3d", "#ffe3b3"]}
flow={90}
stretch={0.8}
contrast={0.8}
repeat={2} // the ramp mirrors twice across the paint
transition={2} // a new palette fades in over 2 seconds
/>Read from the component's own type, so this cannot drift from what it accepts.
| Prop | Type | Default | Description |
|---|---|---|---|
colors | string[] | — | The color ramp, 2 to 6 stops in order. Any CSS color, tokens included. |
scale | number | — | Size of the swirls, 0.5 (fine) to 2.5 (broad). |
warp | number | — | How far the paint folds into itself, 0 (soft waves) to 1 (deep marbling). |
detail | number | — | Fine streaks inside the streams, 0 (smooth) to 1 (detailed). |
flow | number | — | Direction the paint flows, in degrees (0 = right, 90 = up). |
stretch | number | — | How much the streams are drawn out along the flow, 0 to 1. |
repeat | number | — | How many times the ramp repeats across the paint, 1 to 4. Repeats mirror, so there is no hard seam. |
speed | number | — | How fast the paint moves, 0 (still) to 3. |
contrast | number | — | Separation between the ramp colors, 0 (blended) to 1 (bold). |
sheen | number | — | A soft glossy highlight along the folds, 0 to 1. |
saturation | number | — | Color intensity, 0 (grey) to 2 (vivid). 1 keeps the colors as given. |
grain | number | — | Film grain over the paint, 0 to 1. |
grainSize | number | — | Size of one grain in CSS pixels, 1 to 4. |
grainMotion | boolean | — | Let the grain flicker like film instead of holding still. |
transition | number | — | Seconds a change of `colors` takes to fade through. 0 swaps at once. |
seed | number | — | Picks a different pour. |
interactive | boolean | — | The paint bends softly toward the cursor, as if seen through a lens. |
pull | number | — | Strength of that bend, 0 to 1. |
paused | boolean | — | Hold the paint still. |
className | string | — | |
children | ReactNode | — |