FluidGlass
fluid-glassMoves a refractive circular glass lens across a procedural fluid background.
Usage
Basic usage
Put it into the relative container, the component comes with absolute inset-0; move the pointer to see the glass lens to follow the refraction.
<div className="relative h-64 overflow-hidden rounded-xl">
<FluidGlass className="absolute inset-0">
<div className="flex h-full items-center justify-center text-lg font-semibold text-white drop-shadow">
Fluid Glass
</div>
</FluidGlass>
</div>Strong refraction + strong dispersion
Turn up size/refraction/dispersion to simulate thicker glass with more obvious colored edges.
<FluidGlass
size={0.32}
refraction={0.85}
dispersion={0.7}
className="absolute inset-0"
/>Pointer not followed
When followPointer={false}, the lens stops at the center and slowly self-drifts.
<FluidGlass
followPointer={false}
size={0.24}
className="absolute inset-0"
/>Custom color matching
colors Pass any three colors to cover the flowing basemap of the default chart token.
Hulian component library
Fluid Glass · Real-time Refraction
<FluidGlass
colors={[
"oklch(0.72 0.2 30)",
"oklch(0.78 0.16 70)",
"var(--color-chart-3)",
]}
refraction={0.6}
className="absolute inset-0"
>
<div className="flex h-full flex-col items-center justify-center gap-1">
<p className="text-base font-semibold text-white">Hulian Component Library</p>
<p className="text-xs text-white/70">Fluid glass · real-time refraction</p>
</div>
</FluidGlass>When to Use
A whole "fluid glass" background is needed - a programmed flowing gradient base map + a circular glass lens that follows the pointer to refract and enlarge the base map in real time, suitable for hero/block backgrounds. To make a fixed-size glass panel (pill/card), use GlassSurface; to make a partial static magnifying glass, use Lens. FluidGlass is a "fluid full-screen glass background" that is rendered using the ogl WebGL shader.
Import
import { FluidGlass } from "@hulianui/ui"Props
| Name | Type | Default | Description |
|---|---|---|---|
| size | number | 0.26 | The ratio of the lens radius to the short side of the container is 0–1. The larger the refractive area, the wider the refractive area. It is recommended to be 0.15–0.4 |
| refraction | number | 0.5 | Refraction intensity (IOR mapping), the larger the center, the stronger the amplification/distortion, 0=almost transparent, recommended 0–1 |
| dispersion | number | 0.3 | Dispersion strength, simulates edge RGB dispersion edge, 0=off, recommended 0–1 |
| speed | number | 1 | Background flow speed magnification, 0 = background is stationary (the lens still follows the pointer) |
| colors | string[] | chart-1/2/4 | Background gradient color group, take the first 3, you can pass any CSS color |
| followPointer | boolean | true | The lens follows the pointer; stops at the center and drifts slowly when closed |
| className | string | — | Forward the root container className (the root is relative overflow-hidden, Canvas includes absolute inset-0) |
| style | CSSProperties | — | Forward the root container inline style |
Slots
| Slot | Type | Description |
|---|---|---|
| children | ReactNode | Content overlaid on glass background (relative z-10 layered over Canvas) |
Usage Guidelines
- WebGL components (ogl single shader) must be rendered on the client side, and SSR is empty; put into a fixed-height
relative overflow-hiddencontainer and give itclassName="absolute inset-0". - The
colorsfeed token must be prefixed with--color-; the shader color selection is parsed by the component, and the barevar(--primary)is not parsed. - Headless screenshots can be blank before the WebGL shader or context is ready. Verify in a real browser, and avoid reusing a canvas after cleanup calls
loseContext; see [[webgl-canvas-loseContext-poisons-strictmode-remount]]. - Stop the background flow animation in reduced-motion (lens refraction is still there).
Related
BorderBeam · ShineBorder · GlareHover · Lens · AnimatedBeam · OrbitingCircles
Playground
<div className="relative h-64 overflow-hidden rounded-xl">
<FluidGlass
size={0.26}
refraction={0.5}
dispersion={0.3}
speed={1}
followPointer={true}
className="absolute inset-0"
/>
</div>