CSS滤镜blur在hover时为什么会有闪烁问题?
我在做导航菜单的hover效果,想让背景模糊一下,但每次鼠标移上去都会闪一下,特别难受。明明加了transition,但还是不行。
我试过把filter写在父元素上,也试过用will-change,都没用。是不是blur本身的问题?
document.querySelectorAll('.nav-item').forEach(item => {
item.addEventListener('mouseenter', () => {
item.style.filter = 'blur(2px)';
});
item.addEventListener('mouseleave', () => {
item.style.filter = 'blur(0)';
});
});
改成这样:用一个带blur的伪元素,通过opacity控制显隐
或者直接在hover时只改opacity,别改blur值。
浏览器在渲染blur的时候需要对整个图层进行高斯模糊计算,这个开销很大的。你用JS直接改style.filter,鼠标移入移出那一瞬间,浏览器得马上重新计算模糊,帧率跟不上就会闪。
解决方法很简单,别用JS动态改,用CSS的hover和transition:
.nav-item {
transition: filter 0.3s ease;
filter: blur(0);
}
.nav-item:hover {
filter: blur(2px);
}
把JS那段监听代码删掉就行了。
为什么这样就行?因为CSS的transition是浏览器主动管理的,它会尽量做优化。而且你一开始就应该在CSS里写好过渡,浏览器有预判空间。
如果你非要用JS(比如说动态控制要不要模糊),那就用class切换:
item.classList.add('active');
item.classList.remove('active');
然后CSS里写:
.nav-item.active {
filter: blur(2px);
}
这样比直接操作style.filter稍微好一点点,但根本解决方案还是用CSS hover。
will-change: filter 也可以加上,不过大多数情况下不加也够用了。