backdrop-filter属性可以让一个元素后面区域添加图形效果(如模糊或颜色偏移),因为它适用于元素背后的所有元素,为了看到效果,必须使元素或其背景至少部分透明
不使用backdrop-filter属性时
<div class="container">
<div class="child"></div>
</div>
.container {
width: 10vw;
height: 10vw;
background-color: rgba(255, 100, 100, 0.8);
}
.child {
position: fixed;
top: 1vw;
left: 1vw;
right: 1vw;
bottom: 1vw;
background-color: rgba(100, 100, 255, 0.8);
}
此时子元素.child的固定定位是相对于浏览器窗口定位的
当使用backdrop-filter属性时
<div class="container">
<div class="child"></div>
</div>
.container {
width: 10vw;
height: 10vw;
background-color: rgba(255, 100, 100, 0.8);
backdrop-filter: blur(20px);
}
.child {
position: fixed;
top: 1vw;
left: 1vw;
right: 1vw;
bottom: 1vw;
background-color: rgba(100, 100, 255, 0.8);
}
此时子元素.child的固定定位是相对于使用backdrop-filter属性的父元素定位的
因为:使用backdrop-filter属性导致position: fixed;定位失效了
position: fixed的元素相对于屏幕视口(viewport)的位置来指定其位置,并且元素的位置在屏幕滚动时不会改变,但是,在许多特定的场合,指定了position:fixed的元素却无法相对于屏幕视口进行定位
解决方案一:使用伪元素
将backdrop-filter属性添加到伪元素上,通过修改z-index层级关系,实现同样的效果
.container {
width: 10vw;
height: 10vw;
background-color: rgba(255, 100, 100, 0.8);
position: relative;
}
.container::before {
content: '';
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
backdrop-filter: blur(20px);
}
.child {
position: fixed;
top: 1vw;
left: 1vw;
right: 1vw;
bottom: 1vw;
background-color: rgba(100, 100, 255, 0.8);
}
解决方案二:计算
原本使用鼠标的事件对象e,e.pageX、e.pageY就可以获取到位置并实现固定定位,但由于使用了backkdrop-filter属性,使其相对于父元素定位了,那么这样获取到的位置也就不对了,需要计算相对于父元素的位置,从而相对于父元素实现定位
这种方法由于需要针对不同的浏览器进行处理,并且不清楚哪些浏览器会受影响,所以不太推荐
const ua = navigator.userAgent;
// 在IE浏览器和safari浏览器中fixed定位不受backkdrop-filter的影响
const isSpecialBrowser = /Safari|MSIE|Trident\//i.test(ua) && !/Chrome/.test(ua);
const chatToolsContainer = document.getElementById('chat-tools-container');
if(chatToolsContainer && !isSpecialBrowser) {
const chatToolsContainerRect = chatToolsContainer.getBoundingClientRect();
this.tipTop = e.pageY - chatToolsContainerRect.top + 20;
this.tipLeft = e.pageX - chatToolsContainerRect.left + 10;
} else {
this.tipTop = e.pageY + 20;
this.tipLeft = e.pageX + 10;
}