CSS实现毛玻璃效果的一种新方式

今天在逛V站看到一个自推UI组件库的帖子,我觉得很不错,在查看组件样例的时候呢,发现了他的抽屉组件的遮罩可以把整个页面添加毛玻璃效果!我就很惊讶。马上就 F12查看了一下他的实现方式,因为在我映像里还没有一个很简单的的可以直接实现背景元素毛玻璃效果的方式。

其实不光是抽屉组件,其它的一些类 Modal 带有遮罩的组件都有这个毛玻璃的效果,大伙可以点点看看。

好了,不多废话直接开始正题。

CodePen 上的 原 Demo 写的比较杂乱,有很多无关的样式内容,我简化处理了一下。

早年最初的毛玻璃效果就是上面的 Demo 这样的,先在外部容器上添加背景图,并且在当前 “窗口” 上设置一样的背景图,再利用 filter: blur() 属性模糊遮罩层的背景。

但是这个会有一个问题,就是需要把滤镜属性 filter: blur() 设置在一个单独的背景元素或者伪类上,不然会把 窗口 内部的内容也给模糊了。并且会受限制这个我们在后面说。

而是使用新滤镜属性 backdrop-filter: blur() 后的呢,就十分的简单了,可以看下方 演示Demo

可以看到,比最初的毛玻璃实现方式少了一个伪类元素,并且他会直接把遮住的部分添加滤镜效果,不需要考虑被遮住的内容了,也不会影响内部元素。也就是说可以“不受限制”的实现毛玻璃效果。例如在文章最开始提到的,给整个页面元素都加上遮罩。

整个页面添加毛玻璃效果

这在以前只能通过 canvas 成当前页面快照的方式生来实现,可以很明显的感觉到早些时候投入和回报的不成比例,但是现在使用 filter: blur() 可以很轻松的就实现了,投入产出比极高


😍 那这么棒的CSS属性是什么时候被提出的呢?

从张鑫旭大佬的 《CSS新世界》 中了解到:

毛玻璃效果在前端圈形成讨论是在 iOS 7 面世的时候,和高斯模糊不同,毛玻璃的效果不是让当前元素模糊,而是让当前元素所在区域后面的内容模糊…
iOS 7 面世两年后,iOS 9 支持了一个名为 backdrop-filterCSS 属性,它可以非常方便的实现毛玻璃效果…..

可以看到因为苹果提出的特性,所以在 Safari 上的实现会很早(iOS 9 也就是说 2015 年就已经支持了 😱),之后其他浏览器对于该属性的支持都是在 2019 年左右。

关于使用方面,虽然还是处于草案阶段,但是各个现代浏览器已经不同程度的支持了这个属性(2022年07月26日)

  • Chrome 76+Edge 17+Opera 63+ 已经完美支持(Full support),
  • Safari 9+iOS Safari 9+ 需要使用 -webkit- 前缀;
  • Firefox 70+ 比较特别需要打开 layout.css.backdrop-filter.enabledgfx.webrender.all 首选项才行;

一般不会有问题,所以请大家放心。不过最好的实现呢,还是先给元素设置一个半透明的背景色再加上这个 backdrop-filter 属性,这样即使用户的浏览器太陈旧不支持这个属性或者使用的是 Firefox,也可以看到半透明的背景来兜底。

具体也可以查看 MDN 上该属性对于各浏览器兼容度的说明

以至于为什么唯独 Firefox 有些问题,应该是早些版本的时候 WebRender 引发的一个BUG,所以一直没有默认启用。我现在看帖子内还在讨论所以短期内无望了(优先级也已经从P1降为P3)。可以看这篇BUG反馈贴了解。

文章最后推荐一下那位同学肝的UI组件库,我觉得挺不错的,大伙可以去点个Star打个Call
👉 Lew Design

如果不是他的组件库,我到现在都不知道已经有一个那么简单好用可以实现毛玻璃效果的CSS属性了。

最后的最后,张大佬在他的新书中提了一嘴:

限制 backdrop-filter 属性大规模使用的唯一因素就是性能。如果你的页面非常复杂,有很多动画和频繁的交互行为,则 backdrop-filter 属性可能会造成卡顿,此时就需要酌情使用。


📚 文档

filter - CSS | MDN
backdrop-filter - CSS | MDN
Filter Effects Module Level 2 | W3C Editor’s Draft

CSS backdrop-filter简介与苹果iOS毛玻璃效果 « 张鑫旭-鑫空间-鑫生活
CSS - Frosted Glass | CodePen
CSS - Frosted Glass - Simplified | CodePen
Lew Design