必须显式初始化filter起始值,否则blur动画会跳变;transition适合简单交互,@keyframes适合复杂节奏;blur()参数须带单位(如px),推荐范围2–6px;需配合will-change或transform提升图层以保流畅。

filter: blur() 动画必须显式初始化起始值
浏览器不会自动推断 filter 的默认状态,如果元素初始没写 filter: blur(0) 或其他明确值,transition 或 @keyframes 里的模糊变化就会“跳变”——直接从无模糊切到目标值,没有过渡。这不是 bug,是规范行为。
常见错误写法:.img { transition: filter 0.4s; } .img:hover { filter: blur(0); } —— 缺少初始 filter 声明,hover 时动画不触发。
正确做法始终显式定义起点:
- 用
transition:给默认状态加上filter: blur(6px),hover 时设为filter: blur(0) - 用
@keyframes:0% 关键帧必须写全,比如filter: blur(6px) grayscale(100%),不能只在 100% 写 - 多个滤镜组合时,所有值必须统一写在同一行,避免被后续声明覆盖(如
filter: blur(2px); filter: brightness(1.2)会导致前者失效)
transition 和 @keyframes 选哪个更合适
transition 适合简单双向交互,比如悬停、点击切换清晰/模糊;@keyframes 适合需要节奏控制、循环、或非对称变化的场景,比如“呼吸式”渐变、加载占位图脉动、或进入视口时的单次淡入清晰。
立即学习“前端免费学习笔记(深入)”;
性能上两者无本质差异,但使用习惯影响可维护性:
- 鼠标悬停就用
transition:代码短、语义清、易调试 - 要实现 0%→50%→100% 的中间态(如先轻微去灰再完全清晰),必须用
@keyframes - 动画需 JS 控制启停(如滚动触发),推荐绑定类名 +
@keyframes,比反复 toggle:hover更可控
示例(transition):.card img { filter: blur(4px); transition: filter 0.5s cubic-bezier(0.33, 1, 0.68, 1); } .card:hover img { filter: blur(0); }
blur() 值单位和范围必须严格合规
blur() 的参数必须带单位,blur(4) 或 blur(4%) 会被浏览器静默忽略——DevTools 里 filter 字段甚至不显示,排查时容易卡住。
实用范围建议:
- 悬停清晰化:起始值用
blur(2px)~blur(5px),太大显得失真,太小无感知 - 背景遮罩虚化:不超过
blur(6px),iOS Safari 在blur(10px)以上常退化为盒状模糊 - 动画中避免突变:不要从
blur(0)直接到blur(8px),中间加个blur(4px)过渡更自然
移动端尤其注意:安卓旧 WebView 可能不渲染大于 blur(6px) 的值,得靠 @supports (filter: blur(1px)) 包裹并提供降级样式。
硬件加速和图层隔离是流畅的关键
filter: blur() 是重绘密集型操作,大面积元素直接加动画极易掉帧。不优化的话,60fps 很难维持。
两个低成本生效手段:
- 强制图层提升:加
will-change: filter(现代浏览器)或transform: translateZ(0)(兼容老版本) - 限制作用域:用
overflow: hidden包裹容器,防止模糊溢出;伪元素实现背景模糊时,::before必须设z-index: -1并脱离内容流,否则文字也会被糊 - 慎用
display: none:它会中断渲染上下文,导致transition失效;改用opacity: 0; pointer-events: none
真正容易被忽略的是:blur 动画的性能瓶颈不在 JS,而在图层合成阶段。哪怕只是 1px 模糊,没提图层也卡;提了图层,6px 也能跑满 60fps。


















