System.Routing

Liquid Glass

Apple's Liquid Glass, rebuilt from optics: rays are refracted through a curved bezel with Snell's law, baked into an SVG displacement map, and applied to the backdrop.

Chromium only. Using an SVG filter as a backdrop-filter is not part of the CSS spec and only Chromium implements it. In Safari and Firefox the panel degrades to its frost tint and rim shadow, with no refraction.

How it works

The effect is a small ray tracer that runs once per size change, following Maxime Kubryk's write-up of the technique.

1. The surface

The bezel is described by a height function over x ∈ [0, 1], where 0 is the outer edge and 1 is where the glass goes flat. The surface prop picks between four of them — a circular arc, a squircle, the concave complement, and a smootherstep blend of convex and concave that produces a raised lip.

2. The refraction

Incident rays are assumed orthogonal to the background, so the angle of incidence is just the surface tilt — the derivative of the height function, scaled by thickness / bezelWidth. Snell's law (n₁·sin θ₁ = n₂·sin θ₂) gives the refracted angle, and the ray then crosses the glass before landing on the background, so the lateral shift is height · tan(θ₁ − θ₂). Convex profiles keep the landing point inside the panel; concave ones push it out past the border, where there is nothing to sample.

3. The displacement map

Displacement magnitude only depends on distance from the border, so it is computed once along a single radius and then rotated around the shape — a rounded-rect signed distance field supplies both the distance and the normal to point the vector along. The vectors are normalised by the largest magnitude, then written into a canvas with the X component in red and the Y component in green, 128 being neutral. Exactly 128 samples are taken, because an 8-bit channel cannot express any more.

That maximum magnitude comes back as the filter's scale, which is what converts the normalised map into real pixel offsets. Because scale is just an attribute, refraction and aberration can be animated freely — everything else changes the baked geometry and forces a rebuild.

4. The specular rim

A second image encodes a rim light: brightest where the tilted bezel faces specularAngle, fading out on its own as the surface flattens toward the interior. It is screened over the refracted backdrop.

Installation

npx raya-ui@latest add liquid-glass

File Structure

your-project
components
ui
liquid-glass
LiquidGlass.vue
index.ts

Performance notes

  • Building the maps is a full per-pixel pass over the panel, so it is coalesced into one requestAnimationFrame and only runs when the size or the baked geometry changes.
  • Moving, scaling by transform, or animating refraction and aberration costs nothing extra — none of them rebuild the map.
  • Resizing the panel every frame does rebuild it every frame. Prefer transform: scale() for animated size changes.
  • aberration above 0 runs three displacement passes instead of one. Leave it at 0 unless you want the dispersion.

API Reference

Props

surface
"convexSquircle" | "convexCircle" | "concave" | "lip"
"convexSquircle"

Cross-section profile of the bezel. The squircle keeps the flat-to-curve transition smooth when the shape is stretched into a rectangle, which is why Apple favours it. `concave` pushes rays outward past the panel; `lip` raises a rim and dips the centre.

radius
number
24

Corner radius of the panel, in px. Also drives the rounded-rect distance field the vector field is rotated around.

bezelWidth
number
24

How far the curved bezel extends inward from the border, in px. Everything past it is flat glass and refracts nothing.

thickness
number
40

Height of the glass at the end of the bezel, in px. Rays cross this much material before landing on the background, so it scales the displacement directly.

refractiveIndex
number
1.5

Refractive index of the material used in Snell's law. 1 is air and bends nothing; 1.5 is window glass.

refraction
number
1

Artistic multiplier on the simulated displacement. 1 keeps the physics honest; it maps straight onto the filter's `scale`, so it animates without rebuilding the map.

aberration
number
0

Chromatic dispersion as a ratio of the refraction. Above 0 each channel is refracted at its own scale and recombined, which costs two extra displacement passes.

blur
number
2

Gaussian blur applied to the backdrop before it is refracted, in px. Blurring first keeps the bezel from smearing.

specularOpacity
number
0.4

Brightness of the rim light, 0–1.

specularSharpness
number
6

Exponent on the rim falloff. Higher values give a shorter, sharper glint.

specularAngle
number
-60

Direction the light comes from, in degrees.

frost
number
0.05

Opacity of the frosted tint filling the panel, 0–1. Adapts to light and dark via `light-dark()`.

class
string
—

Classes applied to the inner content wrapper.

containerClass
string
—

Classes applied to the outer glass element — use this for sizing and positioning.

Slots

default

Content rendered on top of the glass. It sits above the refracted backdrop and is not itself distorted.

GLASS

EFFECT

Balance

$12,450.00

Drag the card to see the refraction
Settings
24px
40px
1.50
1.00
2px
0.00
0.40
6
-60°
24px
0.05