当前位置: 首页 > 科技观察

CSS奇思妙想-完全兼容磨砂玻璃效果

时间:2023-03-20 21:00:51 科技观察

通过本文,您可以学习如何使用CSSbackdrop-filter在目前不兼容backdrop-filter的firefox浏览器中实现磨砂玻璃(frostedglass)的效果使用一些技巧性的操作,也可以巧妙的实现磨砂玻璃效果,让这种效果真正的用在商业上。什么是backdrop-filterbackground-filterCSS属性允许您向元素后面的区域添加图形效果(例如模糊或颜色偏移)。因为它适用于元素后面的所有元素,所以元素或其背景必须至少部分透明才能看到效果。backdrop-filter和filter很相似,可以取的值都是一样的,只不过一个是作用于整个元素,一个是只作用于元素后面的区域。backdrop-filter和filter的比较我们使用backdrop-filter和filter同时实现毛玻璃效果作为对比,伪代码如下:

Normal
过滤器
背景过滤器
.bg{background:url(image.png);&>div{宽度:300px;高度:200px;background:rgba(255,255,255,.7);}.g-filter{filter:blur(6px);}.g-backdrop-filter{backdrop-filter:blur(6px);}}CodePenDemo--滤镜和背景-滤镜对比[1]在backdrop-filter之前,仅仅在元素背景上实现上述滤镜效果还是非常困难的,而且,对于静态图片,如果背景还是动态背景可以滚动,通常是CSS是无能为力。backdrop-filter的诞生是为了在不影响元素本身的情况下,对元素后面的内容添加过滤器。用它来实现磨砂玻璃(磨砂玻璃)的效果非常方便!background-filter的兼容性backdrop-filter诞生很久了,但是firefox至今不兼容!对于一些已经放弃IE的PC端业务来说,firefox还是要兼容的。如果要使用backdrop-filter实现毛玻璃效果的应用,必须要解决firefox的兼容问题。在firefox中实现毛玻璃效果就OK了。本文的重点是如何在不使用backdrop-filter的情况下,在firefox中尽可能的还原毛玻璃效果。首先,如果你正常使用backdrop-filter,或者上面例子的效果如下,没有毛玻璃效果:使用background-attachment:fixed兼容静态背景图片如果你想使用毛玻璃对火狐的影响。应用磨砂玻璃元素的背景只是一个静态的背景图片,但是有很多方法可以做到。我们只需要在元素后面叠加相同的图片,使用background-attachment:fixed将叠加在元素下方的图片定位到与背景相同的坐标处,然后使用filter:blur()对其进行模糊处理即可。伪代码如下::100vh;display:flex;background-image:url($img);background-repeat:no-repeat;background-attachment:fixed;background-size:cover;}.g-glossy{position:relative;width:600px;高度:300px;背景色:rgba(255,255,255,0.5);溢出:隐藏;z-index:10;&::before{content:"";position:absolute;top:0;left:0;right:0;底部:0;背景图像:url($img);背景重复:不重复;背景附件:固定;背景大小:覆盖;过滤器:模糊(10px);z-index:-1;}}效果如下:这种方法也是在没有backdrop-filter之前在各种浏览器中实现简单毛玻璃效果最常用的方法之一。CodePen演示——使用后台附件:已修复|filter:bulr()实现毛玻璃效果[2]使用background-attachment:fixed兼容静态背景图的缺点。但是这种方法也有两个缺点:1.由于使用了伪元素,叠加了一层背景。因为层级关系,父元素的背景在底部,所以元素本身的背景色并没有完全体现出来。可以对比一下下面两种方法的实际效果图:解决方法是通过另一个伪元素叠加一层背景色,本来应该给父元素自己赋值的。叠加效果如下:CodePenDemo--usebackground-attachment:fixed|filter:bulr()优化毛玻璃效果[3]2.上面的效果很接近,如果要批评的话,就是应用了blurfilter伪元素的边缘有白色的瑕疵。这其实是过滤器本身的问题,也很容易解决。我们只需要稍微扩大伪元素的范围:.g-glossy{overflow:hidden;....&::before{content:"";position:absolute;top:-100px;left:-100px;right:-100px;bottom:-100px;}}定位代码改为top:0px;totop:-100px,所有四个方向都是一样的。这样基本上可以达到100%的仿真。使用moz-element()withfilter:blur()实现复杂背景毛玻璃效果下面这个方法很巧妙。一般来说,使用磨砂玻璃效果的背景元素并不像图片那么简单!通常整个Page背后结构复杂,多层DOM嵌套。那么通过叠加一个简单的图片,是行不通的,我们得想办法模拟整个DOM元素。而恰好在Firefox中,有这样一个属性——moz-element()。什么是-moz-element()?[MDN-element](https://developer.mozilla.org/zh-CN/docs/Web/CSS/element("MDN-element"))说明CSS函数元素()定义从任意HTML元素生成的图像值。image值为live,这意味着如果指定的HTML元素发生变化,则应用该属性的元素的背景也会随之变化。它实际上是一个规范草案,但到目前为止,只有Firefox支持它--我可以使用--CSSelement()[4]:它有什么作用?-moz-element()如何使用那么-moz-element()如何使用呢?简而言之,它可以复制元素内部呈现的UI,并且可以实时同步更改。假设我们有一个像这样的简单结构,元素背景和动态内容:

Content

.g-normal{margin:自动;宽度:200px;高度:200px;动画:change5sinfinite;背景:线性渐变(deeppink,yellowgreen);}p{animation:move5sinfinite;}@keyframeschange{0%{filter:hue-rotate(0);}100%{filter:hue-rotate(360deg);}}@keyframesmove{0%{transform:translate(0,0);}100%{transform:translate(150px,150px);}}它的效果大概是是这样的:我们假设这个结构就是我们页面某一块的内容,那么我们可以使用background:-moz-element(#id)将这个元素中绘制的UI内容完全复制到另一个元素中,来看效果。我们添加一个元素,在这个元素中模拟#bg的内容:

Content

.g-element-copy{margin:auto;width:200px;height:200px;//核心代码背景:-moz-element(#bg);}可以完全复制在另一个element中绘制的UI,并且可以跟踪实时变化:CodePenDemo---moz-elementDemo(FirefoxOnly)[5]在firefox中使用element复制UI,用作磨砂玻璃元素的背景。有了上面的铺垫,下面的内容就比较容易理解了。和上面的background-attachment:fixed方案相比,我们还是通过伪元素叠加了一层背景,但是背景中的内容从一张简单的图片变成了-moz-element()复制的整个UI内容。其次,在上述方案中,我们使用background-attachment:fixed来对齐伪元素中背景图片和叠加图片的位置。这里,我们需要使用Javascript进行简单的计算,确定背景内容元素的相对位置,计算对齐方式。看这样一个DEMO:
模拟真实DOM
模拟真实DOM
模拟真实DOM
模拟真实DOM
模拟真实DOM
模拟真实DOM
模拟真实DOM
模拟真实DOM
>模拟真实DOM
frostedglasseffect其中.g-glossy在normal兼容backdrop-filter时,我们的磨砂玻璃元素,而.g-glossy-firefox不兼容backdrop-filter,我们需要模拟整个DOM背景UI的元素,可以通过CSS控制特征检测CSS@support:核心CSS代码:.bg{//整个页面的DOM结构}.g-glossy{position:fixed;width:600px;height:300px;background-color:rgba(255,255,255,0.5);backdrop-filter:blur(10px);}.g-glossy-firefox{display:none;}@supports(background:-moz-element(#bg)){.g-glossy-firefox{display:block;position:固定;宽度:600px;高度:300px;背景:-moz-element(#bg)no-repeat;滤镜:blur(10px);}}简单解读:兼容backdrop-filter的,.g-glossy中的代码会直接生效,.g-glossy-firefox不会显示。对于Firefox浏览器,因为backdrop-filter一定不能兼容,所以.g-glossy中的backdrop-filter:blur(10px)不会生效,@supports(background:-moz-element(#bg))中的样式会生效,.g-glossy-firefox会使用背景:-moz-element(#bg)不重复;模拟id为bg的元素当然这里我们需要使用一定的JavaScript代码来计算我们模拟的页面UI的元素。g-glossy-firefox是相对于它模拟的#bg元素,即页面布局的一个定位偏差:$(function(){letblur=$('.g-glossy-firefox')[0].style;letoffset=$('.g-glossy').eq(0).offset();functionupdateBlur(){blur.backgroundPosition=`${-window.scrollX-offset.left}px`+`${-window.scrollY-offset.top}px`;}document.addEventListener('scroll',updateBlur,false),updateBlur();});OK,至此,我们就可以在Firefox上完美的实现毛玻璃效果了:它与上面第一种方案相比最大的区别在于它可以模拟多种背景元素,背景元素可以不止一个图片!可以是各种复杂的结构!本方案由冯海流在我的CSS组提供这个思路很巧妙,他本人对本方案给出了完整的解释,可以点此查看:在网页中实现标题栏“毛玻璃”效果[6]】,这篇文章也是他认可的,刷新发布以上效果的完整代码可以点击这里:CodePenDemo--兼容Firefox的复杂背景磨砂玻璃(frosedglass)效果[7]对以上内容做一个简单的总结:可以使用backdrop-filter来兼容它的浏览器实现磨砂玻璃(frostedglass)效果非常简单。对于不兼容backdrop-filter的浏览器,如果只是简单的背景,可以使用background-attachment:fixed和filter:blur()来模拟。对于firefox浏览器,还可以使用moz-element()和filter:blur()来实现复杂的背景磨砂玻璃效果。对于不兼容以上三种效果的其他浏览器,可以通过设置类似background:rgba(255,255,255,0.5)的方式设置磨砂玻璃效果的元素,使其回退为半透明效果,即也是一个非常合理的降级效果,不会导致错误。参考资料[1]CodePenDemo--filter和backdrop-filter对比:https://codepen.io/Chokcoco/pen/WNjebrr[2]CodePenDemo--Usebackground-attachment:fixed|filter:bulr()实现毛玻璃效果:https://codepen.io/Chokcoco/pen/XWRrVma[3]CodePenDemo--使用background-attachment:fixed|过滤器:bulr()优化磨砂玻璃效果:https://codepen.io/Chokcoco/pen/abWbzKG[4]我可以使用--CSSelement():https://caniuse.com/css-element-function[5]CodePenDemo---moz-elementDemo(FirefoxOnly):https://codepen.io/Chokcoco/pen/jOmOPPL[6]在标题栏中实现“毛玻璃”效果网页:https://chaoli.club/index.php/5347[7]CodePenDemo--兼容Firefox的复杂背景磨砂玻璃(frosedglass)效果:https://codepen.io/Chokcoco/pen/ExWqaQG[8]Github--iCSS:https://github.com/chokcoco/iCSS本文转载自微信公众号“iCSS前端趣味”。