HTML + CSS 实现 Liquid Glass 液态玻璃效果

3,433 阅读4分钟

前言

苹果在 WWDC25 发布了全新的液态玻璃(Liquid Glass)设计风格。

image.png

根据苹果官方介绍:

Liquid Glass 统一了 Apple 平台的设计语言,同时提供更生动、更富表达力的用户体验。

640.gif

Liquid Glass 是一种半透明材质,采用「反射+折射+动态变形」的复合渲染机制,营造出类似真实玻璃的视觉质感。它能自动适应环境中的光线变化,具备「可弯曲、轻盈、流动」的特性,像玻璃般浮于 APP 之上。

image.png

Liquid Glass 不是通过淡入淡出来显形和消失,而是通过逐渐改变光线折射和透射,确保形成一种保留材质光学完整性的优雅过渡。

效果分析

正如苹果介绍,Liquid Glass 采用「反射+折射+动态变形」的复合渲染机制。想要通过 HTML + CSS 实现这种效果,不是简单的加一个高斯模糊就行了。

以下是根据苹果目前发布的效果图和已经发布 iOS 26 开发版分析想要实现「液态玻璃」的必要效果:

  1. 边缘折射变形

    image.png

    外轮廓带有液态的「膨胀」效果,这是「液态玻璃」的主要特征。而且强调一下:折射变形仅限于边缘部分,中间部分是没有变形的

  2. 边缘高光 + 浮动阴影

    image.png

    通过边缘处的高光和底部阴影表现出「液态玻璃」的立体感,使按钮看上去是浮在表面上。

  3. 高斯模糊:

    image.png

    通过目前的释放出来的效果图来看,卡片通常的是带有高斯模糊效果的,像一块磨砂玻璃,动态模糊后面的图像内容,有真实透光感。

    image.png

    而处于切换状态时的按钮则没有模糊效果,此时是一块高透玻璃,而非磨砂玻璃。

目前找到的几个实现方案

省流:都是利用 SVG 滤镜。

方案一

有折射效果,这是笔者看到的第一个版本,给我笔者很大启发。

缺点是做成了全局折射,而非边缘折射,而且玻璃拉丝严重,显得浑浊:

image.png

源码:codesandbox.io/p/sandbox/n…

方案二

也是全局折射,而且缺少边缘高光。

image.png

源码:github.com/archisvaze/…

方案三 👍

这个版本是我看到折射效果最好的,非常还原上面所说的边缘折射,中间部份则没有折射

image.png

源码:github.com/shuding/liq…

方案四 👍

折射效果控制的也不错,但中间部分过于模糊,不过应该是可以通过源码调整的:

image.png

源码:codepen.io/Mikhail-Bes…

方案五 👍

笔者还找到了专门实现该效果的库,效果看上去没有那么精致,但整体还可以,而且作者暴露了很多具体参数,可以很方便的调整。不过目前仅支持 React:

image.png

源码:github.com/rdev/liquid…

感兴趣小伙伴可以封装一个通用版本或 Vue 版本。

我的方案

笔者试着用纯 HTML + CSS 实现了一版,没有用到图片滤镜,所以不依赖外部图片,比上面的方案代码都要少,且更加灵活,因为为了直接实现边缘折射效果,只在边缘 5px 使用置换滤镜,但缺点是折射效果不够准确:

实现原理

以上实现了折射效果的方案都是基于 SVG 滤镜(filter) 实现的,区别就是滤镜不一样。

而实现折射效果,主要是利用了映射置换滤镜(feDisplacementMap,他支持以下几个属性:

  • in:表示置换图源,可以自定义图片,也可以使用内置关键字,共 6 个:

    • SourceGraphic:表示使用图形元素自身作为滤镜。

    • SourceAlpha:表示使用图形元素自身的 alpha 通道作为滤镜。

    • BackgroundImage:表示使用滤镜区域下方的 SVG 图形快照。

    • BackgroundAlpha:表示使用滤镜区域下方的 SVG 图形快照的 alpha 通道。

    • FillPaint:表示使用滤镜效果的目标元素的 fill 属性值。

    • StrokePaint:表示使用滤镜效果的目标元素的 stroke 属性值。

  • in2:和 in 一样,第二个置换图源。

  • scale:表示缩放,默认为 0,不缩放。

  • xChannelSelector:表示使用 in2 中的哪个颜色通道沿 x 轴替换 in 中的像素,可选值为:R | G | B | A,默认为 A

  • yChannelSelector:表示使用 in2 中的哪个颜色通道沿 y 轴替换 in 中的像素,可选值为:R | G | B | A,默认为 A

以上方案的折射效果不一样也都是因为这几个属性。