Liquid Glass Button
A frosted backdrop-blur button with layered inset highlights, an animated conic-gradient border, a moving specular sheen, and a shadow that tilts on press. Ported from Petr Knoll.
hover for the sheen · press to tilt
Usage
import { GlassButton } from "~/components/buttons/glass-button";<GlassButton onClick={generate}>Generate</GlassButton>
What's going on
This is Petr Knoll's button, and it's a small masterclass in stacking cheap effects. The pill is translucent with a backdrop-filter: blur, so it actually frosts whatever's behind it (that's why it wants a busy, light background to sit on). Two inset shadows, a dark one up top and a light one along the bottom, give it a glassy edge.
The two moving parts both lean on @property. CSS can't normally animate the angle inside a gradient, but registering an angle custom property as <angle> makes it interpolatable. So the conic-gradient border (masked down to a hairline with mask-composite: exclude) and the diagonal sheen across the face both rotate smoothly on hover and press. A separate blurred element underneath is the shadow, and on :active the whole wrap tilts back with rotate3d so it feels like it's being pushed.
It's all em-based, so it scales with font-size, and it degrades on touch (the angle animations freeze rather than jump).
/* Animatable angles, so the border + sheen can transition smoothly. */@property --glass-1 { syntax: "<angle>"; inherits: false; initial-value: -75deg; }@property --glass-2 { syntax: "<angle>"; inherits: false; initial-value: -45deg; }.glass-btn {all: unset;background: linear-gradient(-75deg,rgba(255,255,255,.05), rgba(255,255,255,.2), rgba(255,255,255,.05));backdrop-filter: blur(clamp(1px, .125em, 4px)); /* the frost */box-shadow:inset 0 .125em .125em rgba(0,0,0,.05),inset 0 -.125em .125em rgba(255,255,255,.5), /* bottom rim light */0 .25em .125em -.125em rgba(0,0,0,.2); /* soft lift */}/* Conic-gradient border masked to a hairline; the angle animates on hover. */.glass-btn::after {background: conic-gradient(from var(--glass-1) at 50% 50%, …);mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);mask-composite: exclude;}.glass-btn:hover::after { --glass-1: -125deg; }
Props
| prop | type | default | description |
|---|---|---|---|
| children | ReactNode | "Generate" | Button label. |
| …props | ButtonHTMLAttributes | — | Any native button prop (onClick, type, aria-*). |
Original by Petr Knoll.