液态玻璃是怎么在浏览器里折射的

约 8 分钟

Apple 在 WWDC 2025 带来的 Liquid Glass 让整个界面像浸在玻璃里。它的核心不是模糊,而是折射——边缘把背景弯出一个透镜。在浏览器里复刻它,靠的是一组低调但强大的 SVG 滤镜原语。

位移贴图:一张图决定光怎么弯

feDisplacementMap 的工作方式很朴素:它读一张图,用像素的 R 通道决定横向位移、G 通道决定纵向位移。灰色(128,128)就是「不动」。所以问题变成:如何画一张「透镜」形状的位移图。

// 圆角矩形内缩一层,边缘模糊——形成一圈透镜带
rect(x + depth, y + depth,
     width - depth * 2, height - depth * 2,
     fill: "#808080",   // 中性:中心不弯
     filter: blur(depth))

一个内缩并模糊的圆角矩形叠加在灰色底上,边缘就得到了一圈从「弯」到「不弯」的渐变。玻璃的厚度感,来自这个渐变带的宽度。

色差:让白光散开

真实玻璃有色散——不同波长的光折射角度不同。做法是把同一位移跑三遍,三次的位移强度递减,各自只保留一个颜色通道,再用 screen 混合叠回来:

R ← 位移 (strength + 2ca)
G ← 位移 (strength + ca)
B ← 位移 (strength)

于是边缘出现细密的彩色镶边,人眼立刻读懂「这是一片有厚度的玻璃」。

只折背景,不折内容

backdrop-filter 是整个方案的关键:它把滤镜应用在元素背后的内容上,元素自身的内容层级完全不受影响。玻璃归玻璃,文字归文字——这也是 Apple 反复强调的纪律:玻璃属于控件层,永远不要糊在正文上。

浏览器的现实

backdrop-filter: url(#filter) 目前只有 Chromium 支持。Safari 和 Firefox 需要降级为 blur + saturate 的毛玻璃——检测时注意 Firefox 会把 url() 解析为合法值却什么也不渲染,任何基于样式解析的检测都会被它骗过,老老实实用 UA 判断吧。

把这些拼起来,再加上随指针移动的镜面高光,就是你现在在这个页面上看到的玻璃。