React Water Caustics Background, a Liquid Light Shader
ProThe pattern light makes on the floor of a swimming pool: a shifting web of bright threads that gather, cross and burn brightest where they meet, with a faint rainbow fringe on their edges. Light falls from the top of the section, and the pointer acts like a lens that pulls the web towards it.

Why caustics look real
Animated Background with Liquid Caustics is a React water caustics background: a WebGL shader that imitates light refracted through a moving water surface, drawing thin interfering filaments with chromatic dispersion behind your content. It runs on Three.js and React Three Fiber in Next.js or any React app.
Real caustics are places where light is concentrated, not added on top. The shader mimics that by crossing two sets of waves at an irrational angle, sharpening each into thin threads and then adding them, so the crossings are the brightest points and the web never settles into a grid.
Colour comes from physics too. The red, green and blue channels read the folded pattern at very slightly different scales, so each filament gets a thin coloured fringe at its edges while its core stays white, the way light splits through a prism.
What the shader models
Crossed wave sets
Two families of waves at an irrational angle, each sharpened into threads by sharpness, then summed so intersections peak.
Turbulent fold
The flow is folded once by turbulence before the waves are read, which tangles the threads into a living web.
Dispersion
Each colour channel samples the folded field at a scale offset of 0.02, giving filaments chromatic edges.
Glow and tilt
glow adds a soft bloom around the web. tilt makes light fall from the top, so the bottom of the section is calmer for text.
Pointer lens
A lens of strength 0.5 and radius 0.75 pulls the flow towards the cursor and brightens it, with a gentle parallax drift.
Deep and shallow palettes
Dark mode is light through deep water: pale cyan threads on navy. Light mode inverts to a shallow pool seen from above, with darker blue threads on a pale surface.
Where the pool floor fits
Use it when
- Wellness, travel, hospitality and ocean related brands.
- Calm, premium hero sections where motion should feel natural rather than digital.
- Light themed sites that want a background that is still clearly water.
- Product launches with a fluid or clarity based message.
Skip it when
- You need a seamless caustics texture for a game engine or 3D software; this is a React page background, not a tileable texture.
- Busy pages where a moving web behind body copy would compete with it.
- Projects without room for Three.js.
- Very small sections, where the threads read as noise without the scale of a pool.
Tune the water
Add three, @react-three/fiber and next-themes, install the block and render your content as children. For calmer water lower speed and turbulence; for crisper threads raise sharpness. dispersion above 0.04 makes the rainbow edges obvious, which can look artificial, so keep it subtle.
Set tilt to zero to light the section evenly, or raise it so the light gathers at the top and leaves the lower half quieter for a headline and buttons. The palette takes three stops: thread colour, mid water and deep water.
npx wensity@latest add animated-background-with-liquid-caustics --type block
import { LiquidCausticsBackground } from "@/components/wensity/blocks/animated-background-with-liquid-caustics";export function SpaHero() {return (<LiquidCausticsBackgroundconfig={{ speed: 0.6, turbulence: 0.8, tilt: 0.7 }}minHeight={620}><div className="mx-auto max-w-2xl px-6 pb-24 pt-64 text-center"><h1 className="text-5xl font-semibold text-sky-950 dark:text-white">Slow down. Breathe in.</h1></div></LiquidCausticsBackground>);}
Props
| Prop | Type | Default | Description |
|---|---|---|---|
config.turbulence | number | 1 | How tangled the web is. Below 0.6 the threads straighten into gentle ripples. |
config.sharpness | number | 5 | Thread tightness. Higher values give thinner, brighter filaments. |
config.dispersion | number | 0.02 | Per channel scale offset that fringes thread edges with colour. |
config.tilt | number | 0.55 | Light falling from the top. Zero lights the whole section evenly. |
config.lens / lensRadius | number | 0.5 / 0.75 | Strength and size of the pointer lens. |
config.glow | number | 0.35 | Soft bloom around the threads. Zero disables it. |
Runtime notes
Still for reduced motion
Visitors with reduced motion enabled get a single frame of the caustic web, no flow and no lens, because respectReducedMotion is on unless you turn it off.
No visibility pause
The render loop continues while mounted even when the section is offscreen. Switch config.animate off from an IntersectionObserver on long pages.
Efficient dispersion
The source folds the flow once and reads all three channels from that single result instead of folding three times, which keeps the chromatic effect cheap.
Base colour first
The section paints its base colour before WebGL starts, so there is no white flash on load, only a moment of flat water colour.
Clickable content
Links and buttons inside children work out of the box. Form controls need pointer-events-auto because the content layer ignores pointer events by default.
Block details
- Category
- Motion
- Renders
- WebGL canvas. Compiles a shader before the first frame
- Theme
- Follows the site theme in light and dark
- Dependencies
@react-three/fiberclsxnext-themestailwind-mergethree- Source
- 601 lines, 21 KB in one file
- Install
wensity add animated-background-with-liquid-caustics --type block- Tags
- webgl, three.js, shader, caustics, refraction, water, light, dark, background
- Last updated

