CSS滤镜blur在hover时为什么会有闪烁问题?

Prog.彦会 阅读 46

我在做导航菜单的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)';
  });
});
我来解答 赞 8 收藏
二维码
手机扫码查看
2 条解答
端木宝娥
blur从0到非0的计算量太大,浏览器扛不住就会闪。

改成这样:用一个带blur的伪元素,通过opacity控制显隐

.nav-item {
position: relative;
}

.nav-item::before {
content: '';
position: absolute;
inset: 0;
background: inherit;
filter: blur(8px);
opacity: 0;
transition: opacity 0.3s;
z-index: -1;
}

.nav-item:hover::before {
opacity: 1;
}


或者直接在hover时只改opacity,别改blur值。
点赞
2026-03-19 14:02
程序员芸倩
这问题我之前也遇到过,说白了就是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 也可以加上,不过大多数情况下不加也够用了。
点赞
2026-03-17 13:01