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>