Filter:blur() 动画卡顿因 cpu 渲染且模糊不可 gpu 加速,应强制合成层、避免 opacity 叠加、用整数模糊值、firefox 需 @supports 降级,并用 animationend + visibility: hidden 彻底隐藏。

filter:blur 动画卡顿或闪烁怎么办
直接上结论:filter:blur() 在动画中默认触发 CPU 渲染,尤其在 chrome 和 safari 中容易掉帧、闪屏,不是 css 性能友好的选择。
根本原因是 filter 属于“复合层触发器”,但模糊计算本身无法被 GPU 硬件加速(除非配合 will-change: filter 或强制提升图层),而浏览器对连续 blur 值的插值又常伴随重绘抖动。
- 加
transform: translateZ(0)或will-change: filter强制创建合成层(仅对现代浏览器有效,Safari 15.4+ 才稳定支持will-change与filter) - 避免在
blur动画同时操作opacity——两者叠加会加剧图层重组,改用rgba()调整文字颜色透明度更稳 - 把
blur(2px)→blur(0)这类小范围变化,换成两段式:先快速模糊(0ms到2px),再淡出(opacity从1到0),比线性混合更顺
文字消散时边缘发虚或锯齿明显
这不是 bug,是 blur() 的本质行为:它对像素做高斯卷积,必然损失锐度。所谓“发虚”,其实是字体抗锯齿信息被模糊冲散后的视觉残留。
关键控制点不在动画本身,而在初始状态:
立即学习“前端免费学习笔记(深入)”;
- 确保文字容器有明确
font-smoothing: antialiased(macos)或-webkit-font-smoothing: antialiased,禁用subpixel-antialiased - 避免在
blur动画期间缩放文字(transform: scale()),否则模糊半径会被等比放大,边缘更糊 - 如果用
@keyframes,别写blur(0.5px)这种亚像素值——浏览器渲染时会四舍五入,造成跳变;统一用整数:blur(0px)、blur(1px)、blur(2px)
Firefox 下 filter 动画完全不生效
Firefox 对 filter 的 CSS 动画支持较晚,直到 v96 才完整支持 blur() 的过渡动画;低于此版本只会跳变,无中间帧。
兼容方案不是加前缀,而是降级处理:
- 用
@supports (filter: blur(1px))包裹动画规则,老 Firefox 自动忽略 - 对不支持的环境,fallback 到纯
opacity淡出 +visibility: hidden隐藏,至少保证功能可达 - 不要依赖
transition: filter 0.3s单独写法,必须显式声明transition: filter 0.3s, opacity 0.3s,否则 Firefox 可能只过渡 opacity
如何让消散后文字真正“消失”而不占布局空间
opacity: 0 不等于隐藏——元素仍占据文档流,且仍可被聚焦、被屏幕阅读器读取。要彻底移除,得组合动作。
最稳妥的做法是用 JavaScript 监听动画结束,再清理 dom 或切类名:
- 监听
animationend事件,检查Event.animationName === 'dissolve'再执行移除 - CSS 里配合定义
.dissolved { opacity: 0; visibility: hidden; pointer-events: none; },动画结束后立即加这个类 - 避免用
display: none直接替换——它会中断 transition,导致消散过程戛然而止
复杂点在于 timing:blur 和 opacity 的 easing 曲线不同步时,人眼会察觉“先糊后隐”或“先隐后糊”。统一用 ease-out,并把 opacity 动画延迟 0.05s,反而更接近自然消散感。