No.02 / Web
liquid-glass-react
复刻 Apple Liquid Glass 的 React 组件库:真实边缘折射、动态高光、优雅的磨砂降级
(01) Overview
Liquid Glass 的难点不在“模糊”,而在边缘:光线穿过曲面时产生的折射与位移,让一块玻璃看起来有厚度。单靠 backdrop-filter: blur() 只能得到一层磨砂,得不到这种体积感。
liquid-glass-react 用 SVG 位移滤镜模拟边缘折射,再叠加随指针移动的动态高光,把效果封装成可组合的 React 组件。在不支持相应滤镜的浏览器里,组件会退回到干净的磨砂样式,而不是出现错位或空白。
项目附带在线演示,可以直接在浏览器里拖动、调整参数,观察折射强度与高光的变化。
(02) Readme GitHub
Liquid Glass React
按 Apple 的设计语言做的一套 React 组件库:会折射背景的玻璃材质、完整的语义色与文字体系、可以拖动的原生控件。
文档站:https://tsdsj.github.io/liquid-glass-react/
独立项目,不是 Apple 官方产品,也不包含 Apple 的字体或图标素材。
安装
pnpm add @ttqtt/liquid-glass-react
需要 React 19。除此之外没有其它运行时依赖。
这个包名在 2026 年 7 月发过 0.1.0 / 0.2.0,那是另一套实现,现已从 registry 整包下架。本项目是完整重写,版本号从 0.0.1 重开。如果你的锁文件里还写着
^0.2.0,它现在解析不到任何东西,改成^0.0.1。
使用
import {
GlassProvider, ToastProvider,
GlassToolbar, ToolbarGroup, ToolbarSpacer, GlassButton,
} from '@ttqtt/liquid-glass-react';
import '@ttqtt/liquid-glass-react/style.css';
export function App() {
return (
<GlassProvider theme="system">
<ToastProvider>
<GlassToolbar aria-label="图片操作">
<ToolbarGroup>
<GlassButton>查看原图</GlassButton>
</ToolbarGroup>
<ToolbarSpacer variant="flexible" />
<ToolbarGroup prominent>
<GlassButton variant="glassProminent">导出</GlassButton>
</ToolbarGroup>
</GlassToolbar>
</ToastProvider>
</GlassProvider>
);
}
样式表在应用入口引一次就够了。
有什么
66 个组件,分成两层——这个分层本身就是这套设计的核心:
| 层 | 组件 |
|---|---|
| 内容(实色,不透明) | Text、Card、Concentric、GroupBox、List、OutlineView、MaterialView、Divider、Kbd、DisclosureGroup |
| 控件 | GlassButton、GlassSegmentedControl、GlassSwitch、GlassCheckbox、RadioGroup、GlassSlider、GlassStepper、GlassProgress、GlassBadge、Picker、ColorWell |
| 输入 | TextField、SearchField |
| 导航 | GlassToolbar、MenuBar、PathBar、TabBar、Sidebar、NavigationBar、GlassTabs、ScrollEdge、PageControl |
| 布局(骨架) | Screen、NavigationStack、SplitView、Inspector、Grid、Form |
| 浮层 | GlassPopover、GlassMenu、GlassMenuButton、ContextMenu、CommandPalette、Tooltip、GlassSheet、GlassAlert、GlassActionSheet、GlassDialog、Panel、ToastProvider、Banner |
玻璃只用在浮起来的那一层。正文、列表、卡片保持不透明——如果满屏都是半透明的,就没有东西真的浮起来了。
几件值得知道的事
- 控件是可以拖的。 分段控件按住当前项就能滑着换,开关可以甩过去,滑块跟手。这是它和“长得像”的实现之间最明显的区别。
- 系统设置会被尊重。 用户开了减少透明度、增强对比度或减少动效,界面立刻跟着变,你不用写任何代码。
- 背景色调由你声明,不靠猜。 用
GlassBackdrop告诉它背后是深是浅,库不会去读取页面像素。 - 每个组件都交还它渲染的那个元素,并且透传
id、style、data-*、aria-*。开发模式下还会对几条最容易踩的设计错误出声——玻璃套玻璃、一屏两个主操作、clear用在没声明色调的地方——生产构建里这些完全不存在。
浏览器支持
默认是磨砂——模糊、提色、高光、边线,四个引擎上一样。边缘折射要自己打开:
<GlassProvider enableSvgAuto>
打开之后,Chromium 系(Chrome、Edge)走 SVG 位移拿到真的折射;Safari 和 Firefox 拿不到,退回磨砂。布局、语义、键盘路径都不依赖这条分支,有 16 项 WebKit / Firefox 用例守着这一点。
模糊是 CSS 链里的第一个函数,滤镜只管位移——所以哪家引擎丢掉了 url(),剩下的仍然是真的磨砂,而不是一块透明的洞。
换主题色
:root, [data-lg-theme="light"] { --lg-accent: #6d28d9; }
[data-lg-theme="dark"] { --lg-accent: #8b5cf6; }
更多在主题指南里。
服务端渲染
服务端先出磨砂效果,到浏览器再升级成折射,中间不会闪。Next.js App Router 只需在根布局里引一次样式表;整个包已经标成客户端组件。
本地开发
pnpm install
pnpm dev # 文档站 http://127.0.0.1:5173
pnpm check # 类型检查 → 构建 → 单元 → SSR → 站点 → 真实 Chrome → WebKit/Firefox
src/
tokens/ 颜色、文字、间距、形状、动效的取值
core/ 不依赖浏览器的几何计算、弹簧、缓存
react/ 组件,按 内容 / 控件 / 输入 / 导航 / 浮层 分目录
styles/ tokens.css + components.css
site/ 文档站
tests/ core 单元测试、SSR 测试、Playwright 浏览器测试
docs/ 设计系统、API、无障碍、迁移、架构、测试口径
验证到什么程度
82 单元 · 7 SSR · 462 真实 Google Chrome · 15 开发模式 · 18 WebKit + Firefox
SSR 那三项跑的是 dist/,也就是真正发出去的那份。玻璃压在真实场景上的文字对比度是从合成后的像素上量的——把两个色值填进计算器不算数,因为玻璃的最终颜色取决于它背后是什么。三个引擎上最差的一块 7.83:1。
还没做完的:
- 屏幕阅读器的实机验证。自动化覆盖了角色、键盘路径和四项系统设置,代替不了真人用 VoiceOver 走一遍。这是最大的未知。
- 触摸真机。已有 4 项模拟 touch 用例,但遮挡、甩动惯性、与系统边缘手势的冲突只有上手才知道。
- 真实低端 GPU 的能耗。现有数据只节流了 CPU,而模糊花的是填充率。
- 浏览器矩阵只跑过一台机器——不是多平台、多版本、开关硬件加速都过了。
详细清单见 docs/known-limitations.md。0.x 阶段仍可能有破坏性改动,每次都给改名对照表。
许可
MIT,见 LICENSE 与 THIRD_PARTY_NOTICES.md。