React Water Caustics Background, a Liquid Light Shader

Pro

The 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.

Animated Background With Liquid Caustics block preview

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
page.tsx
import { LiquidCausticsBackground } from "@/components/wensity/blocks/animated-background-with-liquid-caustics";
export function SpaHero() {
return (
<LiquidCausticsBackground
config={{ 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

PropTypeDefaultDescription
config.turbulencenumber1How tangled the web is. Below 0.6 the threads straighten into gentle ripples.
config.sharpnessnumber5Thread tightness. Higher values give thinner, brighter filaments.
config.dispersionnumber0.02Per channel scale offset that fringes thread edges with colour.
config.tiltnumber0.55Light falling from the top. Zero lights the whole section evenly.
config.lens / lensRadiusnumber0.5 / 0.75Strength and size of the pointer lens.
config.glownumber0.35Soft 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

Animated Background With Liquid Caustics
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

Soft, calm companions