百科.dev
全部条目AI 编程趋势榜开源项目技术资讯提交条目
登录
< 返回工具列表
liquid-glass

liquid-glass

> 设计协作
免费

苹果风格的液态玻璃用于 Web — 一个无头的 React 透镜,可在 Safari、F

526 stars0 点赞4 次浏览
GitHub

工具介绍

苹果风格的液态玻璃用于 Web — 一个无头的 React 透镜,可在 Safari、F

liquid-glass

Real liquid glass for the web. A headless React lens that refracts the live DOM, so the text stays selectable, the links stay clickable, and the motion is real. It renders in Chrome, Safari, and Firefox, with zero runtime dependencies. React is the only peer.

Live demo + docs → glass.samasante.com

Most "liquid glass" libraries use backdrop-filter: url(), which only works in Chromium, so they fall back to a flat blur in Safari and Firefox. The WebGL ones rasterize an html2canvas screenshot, so the text under the glass is frozen and stale. This one runs an SVG displacement filter on the element itself (filter: url()), so it refracts the real, live DOM, and it works across browsers.

bash
npm i @samasante/liquid-glass
# react + react-dom are peer deps
typescript
import { Glass } from "@samasante/liquid-glass";

  Save
;

Wrap any styled box and it becomes a glass material: it frosts and tints the page behind it, rims it with a soft bright edge, and — in Chrome / Edge — bends the live page through it. Your translucent colour is the tint; the children render crisp. No provider, no CSS import, no config. Size and style it with CSS (className, style, Tailwind); change any optic through optics.

The one cross-browser catch (web-platform physics, not a choice). Bending the live page uses backdrop-filter: url(), which ships in Chrome / Edge only. In Safari and Firefox a wrapped `` still frosts + tints + edge-lights — it reads as glass — but it can't bend the live page; bending there needs a copy of what's behind the glass.

To bend in every browser, refract a copy — the same ``, you just tell it what to bend. It works in Chrome, Safari, and Firefox:

  • In-place — give a `` geometry (size + center) and it bends its own children (a hero, a card), no copy to manage:

    typescript
    
      
    ;
  • refract={node} — float a lens over content it doesn't own (a panel over a photo, a loupe over the page). Hand it the node to copy; behind fills the bleed; children render crisp on top:

    typescript
    
      
    ;
  • src / draw + lenses — a /, refracted on the GPU (live media an SVG filter can't reach). One renderer samples the medium and draws many lenses over it, so each control of a video player is its own lens.

One rule across every mode: children are the crisp layer on top. See the copy-paste GlassNotification (panel over a photo) and GlassVideoControls (lenses over a ``).

Why

this other SVG-filter libs WebGL snapshot libs
Refracts live DOM (text selectable, links clickable) yes yes (Chrome only) no, static screenshot
Works in Safari + Firefox yes no, flat blur yes, but a snapshot
Headless / composable yes no, a styled widget no
Bundle tiny, 0 deps small large (three.js)

How it works

A rounded-rect signed-distance field is rasterized to a displacement map (red and green encode X/Y displacement, blue a specular mask). That map feeds an SVG feDisplacementMap on the content via filter: url(#…), with a 3-pass RGB split for chromatic aberration. Geometry is driven by lightweight motion values written imperatively each frame, so a lens follows the pointer or animates at 60fps without re-rendering React.

The hard part is Safari — the WebKit-specific fixes (1× filter, shape-only map regeneration, cache-busting filter ids) are built in. See BROWSERS.md for details and the support matrix.

API

``

Prop Type Default Notes
children ReactNode none The DOM the lens refracts (DOM mode).
refract ReactNode none Refract THIS instead (e.g. a sibling image/video). The children render crisp on top.
behind string auto Solid fill for the bleed edge of a refract copy. Omit it to auto-derive from the page's background; set it for a precise edge over a photo, or "transparent" to opt out.
optics Partial balanced default The look. See the list below.
width, height number | motion fit the element Lens size in full px. Omit and the lens fits the wrapped element.
size number | [w, h] Shorthand for width + height (a number is square).
radius number | motion the element's radius Corner radius in px.
center { x, y } { 0.5, 0.5 } Lens centre as a fraction (0 to 1) of the element — for a positioned or moving lens (a slider thumb, a video control).
src, draw string, fn A video URL or a per-frame canvas painter (WebGL mode).
filterResolution number 1 Chromium-only supersample (2 is crisp). Forced to 1 in Safari.
live boolean false Re-rasterize every frame for self-animating refracted content (Safari).

width, height, radius, and center.x / center.y take a plain number or a motion value (anything with { get(); on('change', cb) }, including a framer-motion MotionValue), so a control can animate them at 60fps.

Optics (optics={{ … }})

One GlassOptics vocabulary (the look, with no geometry) drives both the DOM `` and the WebGL surface below.

  • strength: refraction strength (the most a pixel moves, a 0 to 1 fraction of the box). scaleX and scaleY override it per axis.
  • depth: how far the bend reaches in from the edge (0 to 1). It also gates curvature.
  • curvature: the convex dome (0 to 1), the magnified "liquid" middle. depth gates it, so at a low depth the centre stays flat.
  • dispersion: chromatic aberration, the colour split at the edges.
  • bend: the rim refraction (0 to 1) — the "liquid" lip; extra inward refraction in a thin band at the edge so the background wraps at the contour. 0 is a plain magnifier.
  • bendWidth: the width of that band, a 0 to 1 fraction of min(W, H). Default 0.16.
  • sheen, sheenWidth, sheenFalloff, sheenAngle: the directional edge highlight (intensity, thickness, falloff, and the angle it pools toward). specular is the overall gain.
  • glow, glowSpread, glowFalloff: the soft inner glow.
  • frost: frosted blur. brightness: the veil. splay: corner splay.
  • sheenDark and the *Shadow fields are DOM `` only. On the WebGL surface, use CSS on the container instead.

Defaults

One balanced default look ships out of the box, with no presets to pick from. Override any optic through optics: ``.

Motion utilities (opt-in, for building interactive controls)

glassValue, animateGlassValue, deriveGlass, cubicBezier, glassEase, useLensWobble (velocity squash-stretch), rubberBand, and GlassDiv (a transform-only div). None of them are required to use ``.

Video, canvas, and many lenses over one surface

Safari won't SVG-filter a live , so for media runs one WebGL renderer that samples the medium and draws every lens from it. Pass src (a video) or draw (a per-frame `` painter), and a full-px lenses={[{ x, y, w, h, radius }]} array (one optics, shared) for many lenses over one surface — each control of a video player is its own lens bending the footage. The interactive controls are the children, crisp on top.

typescript
import { Glass, type GlassSurfaceLens } from "@samasante/liquid-glass";

const lenses: GlassSurfaceLens[] = [
  { x: 0.27, y: 0.5, w: 62, h: 62, radius: 31 }, // rewind
  { x: 0.5,  y: 0.5, w: 104, h: 104, radius: 52 }, // play / pause
  { x: 0.73, y: 0.5, w: 62, h: 62, radius: 31 }, // forward
];

  {/* crisp transport controls, positioned over the lenses */}
;

// A generative canvas: pass `draw`; the lens refracts the painted frame.
 paint(ctx, t)} size={160} center={pt} />;

You drive playback yourself with videoRef + paused (plus poster / loop / muted / autoPlay / crossOrigin) — a normal controlled component, no context. GlassSurfaceLens types the lenses array. The full player is in the copy-paste GlassVideoControls example.

Components (copy and own them)

Finished components live in examples/ as code you own and restyle: a video player (GlassVideoControls), and macOS-style switch, slider, notification, and context menu panels.

The glass part is tiny — a few props. The line count in the examples is the accessible, interactive shell (a real ``, drag, keyboard, ARIA), not the lens. Here's the glass-only essence of each:

typescript
// Switch — the lens IS the thumb; it slides 0→1 and bends the track through it.

  

// Slider — a gentler bend; the handle drives the lens, refracting the fill beneath.

  

// Notification / menu — a panel over a photo: it refracts a copy of the wallpaper;
// the crisp content + border sit on top (see the example for the full card).
} behind="#222" />

Copy any file from examples/: the engine ships on npm (versioned, you get fixes) while the components are yours to own and restyle.

Browser support

Chrome and Edge, Safari (including iOS), and Firefox. See BROWSERS.md.

Credit

An implementation of the SDF displacement-map glass technique that Apple popularized as "Liquid Glass", following the approach Aave's team documented in Building glass for the web. Thanks also to liquid-dom for another take on glass in the browser. Not affiliated with or endorsed by Apple.

License

MIT © Sam Asante

Issues· 0 开放

查看全部 Issues在 GitHub 打开

暂无开放 Issues,或尚未同步最近议题。

> 标签

开发者工具

暂无评论,来聊聊你的看法吧

> 工具信息

发布日期2026年9月9日
最后更新2026年9月17日
分类设计协作
定价免费

> 相关工具

F
Figma
协作式界面设计工具
S
sketch-wakatime
Sketch plugin for automatic time tracking and metrics generated from your Sketch usage.
Q
QuickColor
Quickly apply fills from the global or document color palettes to selected elements - 🎨