Liquid Glass: Glass that flows.
A liquid glass effect for React and the web: thick glass shapes bend a bright wallpaper or your own image at their bezels, with specular edges, rendered live in WebGPU, Safari included.
Part of the Free collection for Aperveil 1.0. Public live preview and Color Looks are open. Free Export Kits do not require an account. Purchasing is not available yet.
Color Looks
THE SYSTEM BEHIND THE SURFACE
Inside Liquid Glass.
Liquid Glass sets thick, clear glass shapes over a bright ribbon wallpaper, or over an image or video you choose, after the material Apple introduced in 2025. Each shape is a slab with a rounded bezel: through its flat middle the wallpaper is barely disturbed, while the bezel bends it hard, the way a lens's edge does, splitting it into faint color fringes. A specular line runs along the edge facing the light and a fainter one along the opposite edge; the body is lightly frosted and lifted toward a pale tint, and casts a soft shadow. The shapes drift, meet and flow together like drops of liquid, and a drop follows the cursor and merges with them.
Liquid Glass bends what it draws itself, its ribbon wallpaper or one image or video you give it; it cannot refract the live HTML of your page, because no web API lets a shader read the page's pixels. Its shapes are a composition you can move and size, not your own interface elements.
2.294 ms GPU timestamp median; p95 3.146 ms. 1440x900 @ dpr 1.5; Apple M2 (8-core GPU), Metal driver on macOS Version 26.6.2 (Build 25G83); measured 2026-10-22. This is a recorded headless sample, not a browser FPS or mobile-performance guarantee.
Position
Where the glass sits in the frame.
Size
Size of the glass shapes.
Bezel
Width of the rounded edge that bends the light.
Thickness
How far the glass bends what lies behind it.
Color Looks preserve these settings. Open the editor for all 19 controls.
KEEP THE SOURCE. KEEP THE CONTROL.
From preview to your project.
Choose a Look, tune it in the editor, then download the Export Kit. Install the runtime and copy the generated component into your project.
Every control in the editor is a typed prop. Leave a prop out to keep the value you exported; change one and the running shader updates without restarting. Give the surface a size and pass fallback for browsers without WebGPU.
The component is already marked "use client": in Next.js, import it into any page or layout and give its container an explicit size. Keep headings, links and accessible content in HTML above the decorative canvas.
Part of the Free collection for Aperveil 1.0. Public live preview and Color Looks are open. Free Export Kits do not require an account. Purchasing is not available yet.
Open editor & exportUsage example — download LiquidGlass.tsx from the editor first. This example imports that local file; it is not the shader component itself.
Add it with npx @aperveil/cli add shader liquid-glass, or download the Export Kit from the editor and copy the component into your project.
Usage example for vue/LiquidGlass.vue from the Export Kit. Vue 3.5 or newer, Nuxt included: it renders an empty canvas on the server and starts in the browser, so it needs no <ClientOnly>.
Same props and values as the React component.
Usage example for html/aperveil-liquid-glass.js from the Export Kit. No install and no build step: keep the two files of the kit's html folder together.
Same props and values as the React component.
Download aperveil-shader-liquid-glass.zip from the editor: Install, then WordPress. WordPress 6.5 or newer: a plugin with a block that holds your own content in front of the shader, and a shortcode for page builders.
The values you choose in the editor are baked into the plugin.
Copy LiquidGlass.tsx from the editor: Install, then Framer. It opens on the values you chose.
- In Framer, open Assets, then Code, and add a new code file named LiquidGlass.
- Replace its sample code with your copy and save.
- Drag Liquid Glass onto the canvas. Its Color Looks and every control are in the property panel.
The same controls as the React component, in Framer's panel. Framer guide
| Prop | Type | Default | What it does |
|---|---|---|---|
| colorA | `#${string}` | "#0a2fd9" | Deep. The wallpaper's deepest color, behind everything. Accepts #RRGGBB. |
| colorB | `#${string}` | "#2c8dff" | Ribbon. The body of the ribbons. Accepts #RRGGBB. |
| colorC | `#${string}` | "#bff1ff" | Light. The lit crest of each ribbon. Accepts #RRGGBB. |
| colorD | `#${string}` | "#7a3cff" | Accent. The wallpaper's second ground, toward the lower corner. Accepts #RRGGBB. |
| tintColor | `#${string}` | "#eef6ff" | Glass tint. The pale color the glass lifts what it shows toward. Accepts #RRGGBB. |
| position | readonly [number, number] | [0.5, 0.5] | Position. Where the glass sits in the frame. Accepts x 0–1, y 0–1. |
| size | number | 1 | Size of the glass shapes. Accepts 0.4–2, step 0.01. |
| bezel | number | 0.1 | Bezel. Width of the rounded edge that bends the light. Accepts 0.02–0.2, step 0.001. |
| thickness | number | 1 | Thickness. How far the glass bends what lies behind it. Accepts 0–2, step 0.01. |
| dispersion | number | 0.8 | Dispersion. Color fringes along the bezel, as glass splits light. Accepts 0–2, step 0.01. |
| frost | number | 0.5 | Frost. Blur inside the glass. Accepts 0–2, step 0.01. |
| translucency | number | 0.3 | Translucency. How far the glass lifts what it shows toward its tint. Accepts 0–1, step 0.01. |
| specular | number | 1 | Specular. The light along the edges. Accepts 0–2, step 0.01. |
| shadow | number | 0.6 | Shadow. The soft shadow the glass casts. Accepts 0–1.5, step 0.01. |
| merge | number | 0.7 | Liquid. How readily touching shapes flow into one. Accepts 0–1.5, step 0.01. |
| flowSpeed | number | 1 | Speed of the ribbons and the drifting glass. Accepts 0–3, step 0.01. |
| drift | number | 1 | Drift. How far the shapes wander, meeting and parting. Accepts 0–2, step 0.01. |
| interaction | number | 1 | Cursor drop. Size of the drop that follows the cursor and merges with the glass. Zero turns it off. Accepts 0–2, step 0.01. |
| opacity | number | 1 | Opacity of the whole effect over the page. Accepts 0–1, step 0.01. |
| src | string | — | The video or image it plays. A URL to an MP4, WebM, MOV, JPG, PNG or WebP, on your own site or on a server that allows it (CORS). Left out, it plays its own clip; an empty string shows its own scene. |
| mediaFocus | readonly [number, number] | — | Where the subject sits. Its place in the picture, from the top left, kept in view when the picture is cropped to fill. Accepts 0–1 for each. |
| mediaKind | "video" | "image" | — | Video or image. Only needed when the URL does not end in a file extension. Accepts "video" or "image". |
| className | string | — | Size and place the surface. The canvas fills this box, so give it a width and a height. |
| style | CSSProperties | — | Inline styles for the surface box. |
| paused | boolean | false | Holds the current frame. Use it for a pause control or for sections scrolled out of view. |
| fallback | ReactNode | null | Shown instead of the canvas without WebGPU. Also shown if rendering fails. A poster image or a CSS gradient works well. |
| onReady | () => void | — | The first frame has been drawn. |
| onError | (error: unknown) => void | — | Rendering failed; the fallback is shown. |
- colorA · `#${string}` = "#0a2fd9"
- Deep. The wallpaper's deepest color, behind everything. Accepts #RRGGBB.
- colorB · `#${string}` = "#2c8dff"
- Ribbon. The body of the ribbons. Accepts #RRGGBB.
- colorC · `#${string}` = "#bff1ff"
- Light. The lit crest of each ribbon. Accepts #RRGGBB.
- colorD · `#${string}` = "#7a3cff"
- Accent. The wallpaper's second ground, toward the lower corner. Accepts #RRGGBB.
- tintColor · `#${string}` = "#eef6ff"
- Glass tint. The pale color the glass lifts what it shows toward. Accepts #RRGGBB.
- position · readonly [number, number] = [0.5, 0.5]
- Position. Where the glass sits in the frame. Accepts x 0–1, y 0–1.
- size · number = 1
- Size of the glass shapes. Accepts 0.4–2, step 0.01.
- bezel · number = 0.1
- Bezel. Width of the rounded edge that bends the light. Accepts 0.02–0.2, step 0.001.
- thickness · number = 1
- Thickness. How far the glass bends what lies behind it. Accepts 0–2, step 0.01.
- dispersion · number = 0.8
- Dispersion. Color fringes along the bezel, as glass splits light. Accepts 0–2, step 0.01.
- frost · number = 0.5
- Frost. Blur inside the glass. Accepts 0–2, step 0.01.
- translucency · number = 0.3
- Translucency. How far the glass lifts what it shows toward its tint. Accepts 0–1, step 0.01.
- specular · number = 1
- Specular. The light along the edges. Accepts 0–2, step 0.01.
- shadow · number = 0.6
- Shadow. The soft shadow the glass casts. Accepts 0–1.5, step 0.01.
- merge · number = 0.7
- Liquid. How readily touching shapes flow into one. Accepts 0–1.5, step 0.01.
- flowSpeed · number = 1
- Speed of the ribbons and the drifting glass. Accepts 0–3, step 0.01.
- drift · number = 1
- Drift. How far the shapes wander, meeting and parting. Accepts 0–2, step 0.01.
- interaction · number = 1
- Cursor drop. Size of the drop that follows the cursor and merges with the glass. Zero turns it off. Accepts 0–2, step 0.01.
- opacity · number = 1
- Opacity of the whole effect over the page. Accepts 0–1, step 0.01.
- src · string
- The video or image it plays. A URL to an MP4, WebM, MOV, JPG, PNG or WebP, on your own site or on a server that allows it (CORS). Left out, it plays its own clip; an empty string shows its own scene.
- mediaFocus · readonly [number, number]
- Where the subject sits. Its place in the picture, from the top left, kept in view when the picture is cropped to fill. Accepts 0–1 for each.
- mediaKind · "video" | "image"
- Video or image. Only needed when the URL does not end in a file extension. Accepts "video" or "image".
- className · string
- Size and place the surface. The canvas fills this box, so give it a width and a height.
- style · CSSProperties
- Inline styles for the surface box.
- paused · boolean = false
- Holds the current frame. Use it for a pause control or for sections scrolled out of view.
- fallback · ReactNode = null
- Shown instead of the canvas without WebGPU. Also shown if rendering fails. A poster image or a CSS gradient works well.
- onReady · () => void
- The first frame has been drawn.
- onError · (error: unknown) => void
- Rendering failed; the fallback is shown.
Every prop is optional. Numbers are clamped to their range; an invalid value keeps the default.
THE SURFACE IN CONTEXT
Made for a real interface.
Open an app landing, a design-tool homepage or a product launch with the glass look visitors now know from their own devices, beside the copy rather than under it: the composition sits to one side and your image can lie behind it.

Design system
Clear by design.
An illustrative design-system front page beside a composition of liquid glass.
An illustrative layout. Your content stays in HTML; the shader sets the atmosphere.
Try this surface in the editorA FEW USEFUL DETAILS
Before you ship.
What this surface does, where it fits, and where it stops.
ANOTHER WAY TO SEE IT
Keep exploring.
YOUR COLORS. YOUR CONTEXT.


