Snell refraction · SVG displacement · backdrop-filter

Glass that bends what sits behind it.

One ES module, no dependencies. Custom elements for switches, sliders and segmented controls, classes for buttons, fields, panels and menus, and data-glass for anything else. Chromium only.

Bench controls

Specimens

Components

Each snippet below is the exact markup of the specimen above it. Native inputs do the work underneath, so forms, labels and keyboard support behave as usual.

Buttons

Pill, round and tinted. They swell on press.

Switch

The thumb turns into a lip-profile lens while pressed. Wraps a native checkbox with role="switch".

Slider

Press and drag: the thumb becomes a lens over the track. Wraps <input type="range">.

Segmented control

Equal-width segments with a sliding glass indicator. Arrow keys move the selection and fire change.

Tab bar & pill nav

The same element with .lg-tabbar. Give it links instead of buttons for page navigation (aria-current), like the dock at the bottom of this page.

Search field

A label wrapping a native input, so clicking anywhere on the glass focuses it.


Menu

The Popover API plus anchor positioning, with no positioning script. Picking an item closes it.

CALIBRATION · NOW Lens 2 is back in spec Wavefront error 0.04 λ RMS at 633 nm.

Panel

A rounded container for cards, sheets and notifications. Works on <dialog> too.

Any element

Any element

data-glass on anything with a border radius. Tune it per element with --lg-* properties, or call glass(el, opts).

Playground

Every option, live

Geometry changes (size, radius, bezel, thickness, profile, index, light, zoom) rebuild the maps. Refraction, blur, saturation and specular only change filter attributes, so they are cheap to animate.

Glass
profile
Generated map
Generated map · R = x shift, G = y shift, B = rim light

Reference

API

Load the module once with <script type="module" src="liquid-glass.js"></script>. It adds its styles in a cascade layer, so any unlayered CSS of yours wins.

Option Default Effect
--lg-profile squircle Bezel shape: squircle, circle, lip or concave
--lg-bezel auto Width of the curved edge in px (auto = 0.8 × radius)
--lg-thickness auto Glass height in px (auto = 1.2 × bezel). More = stronger bend
--lg-ior 1.5 Refractive index
--lg-refraction 1 Multiplier on the physical displacement
--lg-blur 1 Frost, as a Gaussian blur in px
--lg-saturation 5 Colour boost under the rim highlight
--lg-specular 0.7 Rim highlight opacity
--lg-light 225 Light angle in degrees (0 = from the right, 90 = from below)
--lg-zoom 1 Magnification of the flat centre
--lg-antialias 1 Smoothing of zoomed pixels, scaled to zoom and screen density. 0 turns it off, 2 doubles it
Piece Usage
glass(el, opts) Applies glass to any element and returns { filter, update(opts), destroy() }. Also available as el.glass.
[data-glass] Applied automatically, including to elements added later. Removing the attribute or the element cleans up. The glass is drawn on the element's ::before, so keep that pseudo-element free and avoid opacity below 1 on the element.
<lg-switch> Attributes pass through to the inner checkbox (name, checked, disabled…). Property .checked.
<lg-slider> min, max, step, value, name pass through. Property .value.
<lg-segmented> Children are the segments. .value = selected index, fires change. Add .lg-tabbar for icon tabs.
.lg-btn Variants .lg-round and .lg-tinted
.lg-field · .lg-panel · .lg-menu Search field, container, popover menu
--lg-accent · --lg-tint Theme colour and glass fill. Normal inherited custom properties.
Bench Components Playground API