直接写 transition: filter 没反应的根本原因是 img 默认为内联元素且部分浏览器(如旧版 Safari)对其 filter 过渡支持差,加之图片未加载完成就渲染导致 blur() 插值被跳过;必须显式设置 display: block/inline-block、等待 load 事件后再切换类、初始样式明确定义 filter: blur(4px)、单位用 px、transition 写全时长和缓动函数,多 filter 函数顺序数量类型须严格一致,避免 drop-shadow() 等不支持过渡的函数。

为什么直接写 transition: filter 没反应
常见现象是图片“啪”一下就变清晰,或者根本没模糊态。根本原因不是 CSS 写错,而是:<img> 默认是内联元素,部分浏览器(尤其是旧版 Safari)对内联元素的 filter 过渡支持极差;另外,图片还没真正加载完成,DOM 就已渲染,blur() 值被跳过插值计算。
- 必须给
<img>显式加display: block或display: inline-block - 不能靠 CSS 自动触发过渡——得等
load事件 fired 后再加类切换状态 - 初始样式里必须写明
filter: blur(4px),不能只在 hover 或 loaded 类里定义 -
blur()的单位必须是px,写成blur(4)或blur(0.5rem)都会失效
filter 过渡必须带完整参数和缓动函数
transition: filter; 等于无效,浏览器不会自动补时长和缓动。Safari 尤其严格,漏掉任何一项都会退化为硬切。
- 必须写全:例如
transition: filter 0.4s cubic-bezier(0.22, 0.61, 0.36, 1) - 多个 filter 函数混用时(比如
blur()+grayscale()),起始和结束状态的函数顺序、数量、类型必须完全一致 - 哪怕某个函数值没变,也要显式写出默认值,例如
brightness(1)、contrast(1) - 避免混入不支持过渡的函数(如
drop-shadow()),否则整个 filter 链可能失效
伪元素方案:背景图模糊→清晰怎么搞
直接给容器加 filter: blur() 会让文字、按钮一起糊掉——因为 background-image 不是独立图层,它是元素绘制的一部分。
- 正确做法是用
::before或::after伪元素承载背景,设position: absolute+z-index: -1 - 伪元素上必须提前声明
will-change: filter,否则 Chrome/Safari 可能不启用 GPU 合成 - 初始状态写
filter: blur(8px),目标状态写filter: blur(0px),单位一个都不能少 - 父容器本身不能设
background,否则和伪元素叠加导致颜色异常
动画 vs 过渡:选哪个更可控
用 @keyframes 写动画适合「自动触发」场景(比如页面一打开就执行),而 transition 更适合「按需触发」(如加载完成、用户交互)。两者底层都依赖 filter: blur() 插值,但行为逻辑不同。
立即学习“前端免费学习笔记(深入)”;
- 动画需配
animation-fill-mode: forwards,否则结束后恢复初始blur值 - 过渡更适合配合 JS 控制时机,比如监听
img.addEventListener('load', () => el.classList.add('loaded')) - 移动端性能敏感,
blur值建议控制在 2–6px,超过 8px 在中低端设备上易掉帧 - iOS Safari 16.6 之前对
filter过渡支持不稳定,可加-webkit-filter兜底,但别滥用在父容器上
load 事件是否真代表图像解码完成?will-change 加在哪一层才不引发重排?这些细节一旦漏掉,效果就断在用户手机上。


















