shadcn.io is not affiliated with official shadcn/ui
The bright net of light that sways across a pool floor on a sunny day: thin lines of light over blue water, glowing where they meet. Two nets of light, each a honeycomb bent by an SVG noise filter that's drawn once, drift in different directions and glow brighter where they cross, so the pattern keeps changing. Only their wrappers move, by CSS transforms, so the filter never runs again and no script runs.
Use it behind an aquatic product hero, a swimming school or a diving and travel page. For the water around the light, with shafts and rising motes, use Underwater; for a cell network that changes cell by cell, Voronoi; for rings spreading on a still surface, Drops; for the open sea out to the horizon, Ocean.
Installation
Usage
import { Caustics } from "@/components/ui/caustics";<Caustics className="flex min-h-[420px] items-center justify-center">
<h1 className="text-5xl font-semibold">Dive into the deep end</h1>
</Caustics>Caustics is a container: whatever you put inside sits on top of the water, in normal flow. It paints its own water, 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 palette follows the colour scheme: a sunny pool with white light on a light page, a night pool with cyan light on a dark one.
Demos
Subtle
intensity="subtle" holds the light back behind body text, and scale={1.5} makes the cells half as big again, here in a small card.
Neon
waterColor and lightColor take any CSS colours, used in both colour schemes: here an indigo pool with pink light.
Accessibility
The water is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion both nets stand still, a still picture of the pool floor. Nothing flashes: the nets drift slowly, with no change in brightness.
Put copy in your foreground colour (text-foreground). Between the lines it keeps 6:1 on a light page and about 9:1 on a dark one. Where a bright line crosses a letter it falls to about 5.6:1 on a light page but about 3.2:1 on a dark one, fine for a headline: for body text on dark pages use intensity="subtle", which keeps it above 5:1. The light is dimmer on a dark page for this reason.
FAQ
What is a caustic?
The net of bright lines a wavy water surface focuses onto the floor below it. Each ripple acts as a small lens, so the light gathers into curved lines around darker cells.
How is it made?
A hexagon pattern bent by a static SVG turbulence filter, drawn once when the background first shows. Two copies of different sizes, one turned, drift in different directions and glow where they cross. The filter itself never animates, so moving the nets costs no repaints.
How do I change the colours?
Pass waterColor for the water and lightColor for the light, any CSS colours; they then apply in both colour schemes. By default both are tuned per scheme: a sunny pool on a light page and a night pool on a dark one. You can also set --caustics-water and --caustics-light in your CSS.
Can I make the net tighter or looser?
Yes: scale sizes the cells (1 by default, from 0.25 to 4), so 2 gives broad cells and 0.5 a tight net. speed sets the drift: 0.5 is calmer, 2 like a windy day.
API Reference
Caustics
<div> data-slot="caustics"
intensity?"subtle" | "medium" | "strong"
How bright the net of light is: subtle behind body text, strong
for a sunny pool.
- Type
"subtle" | "medium" | "strong"- Default
"medium"
lightColor?string
The light's colour, any CSS colour. By default near-white on a light page and cyan on a dark one.
scale?number
The cells' size, a multiplier: 2 is twice as big, 0.5 half. @default 1.
- Default
1
speed?number
How fast the nets drift: 2 is twice as fast, 0.5 half as fast.
- Default
1
waterColor?string
The water's colour, any CSS colour. By default a sunny aqua on a light page and a night-pool navy on a dark one.
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.
--caustics-lstring--caustics-lightstring
The light's colour (near-white, cyan on a dark page).
--caustics-speedstring
The drift's speed, a multiplier (1).
--caustics-waterstring
The water's colour (aqua, navy on a dark page).
Related
- Pro


Underwater Background
WeatherThe water around the light
- Pro


Voronoi Background
GenerativeA glass mosaic that changes pane by pane
- Pro


Drops Background
WavesRings on a still surface
- Pro


Ocean Background
WavesThe open sea, out to the horizon
- Pro


Honeycomb Background
GridsRegular hexagon cells
- Pro


Interference Background
GenerativeWave fringes from two sources