图片模糊到清晰效果本质是CSS过渡实现的视觉占位,需设display:block、监听load事件并用.loaded类触发filter/opacity过渡,避免内联元素兼容性问题及过渡失效。

图片模糊到清晰的加载效果,本质是用 filter:blur() + opacity 配合 CSS 过渡实现的「视觉占位+渐进呈现」,不是真正控制图片解码或加载时机;它只在图片已加载完成的前提下起作用。
为什么直接对 <img alt="CSS如何实现图片模糊到清晰的平滑加载_利用filter:blur与opacity" > 用 filter:blur(5px) + transition 不一定生效
常见现象:图片一闪就清晰,过渡没动;或模糊态根本没渲染出来。原因有三:
-
<img alt="CSS如何实现图片模糊到清晰的平滑加载_利用filter:blur与opacity" >默认是内联元素,filter在部分浏览器(尤其旧版 Safari)对内联元素过渡支持不稳定,必须显式设display: block或inline-block - 图片加载完成前 DOM 已渲染,但此时
blur值可能被浏览器优化跳过(尤其 src 是 data URL 或本地路径时) - 没处理加载状态:图片还没
load事件触发,就提前移除了模糊类,导致过渡丢失
正确做法:用 img.addEventListener('load', ...) 触发类切换
必须等图片真实加载完毕再开始过渡,否则 blur → none 的动画会失效。推荐结构如下:
<img src="photo.jpg" class="blur-up" alt="">
CSS 中定义初始态和过渡态:
立即学习“前端免费学习笔记(深入)”;
.blur-up {
filter: blur(6px);
opacity: 1;
transition: filter 0.4s cubic-bezier(0.22, 0.61, 0.36, 1),
opacity 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
/* 必须加 display,否则 Safari 可能不触发 filter 过渡 */
display: block;
}
.blur-up.loaded {
filter: blur(0);
opacity: 1;
}
JS 控制加载后加类:
document.querySelectorAll('img.blur-up').forEach(img => {
if (img.complete) {
img.classList.add('loaded');
} else {
img.addEventListener('load', () => img.classList.add('loaded'));
}
});
opacity 要不要一起过渡?取决于你是否需要淡入
纯模糊变清晰,opacity 可以保持为 1;但加 opacity 过渡能掩盖图片尺寸未定导致的布局抖动,也更符合「渐进加载」直觉:
- 如果图片宽高已知(如设置了
width/height属性或 CSS),可只过渡filter - 如果宽高未知(响应式、CMS 输出图),建议同时过渡
opacity,并给容器设min-height防止内容上跳 - 注意:不要用
opacity: 0 → 1,而是从1 → 1(即不透明度不变),否则会多一次淡入,和模糊感不匹配
性能与兼容性要注意这些点
filter: blur() 在低端 Android 或 iOS 13 以下设备上可能卡顿,且无法硬件加速。稳妥方案:
- 避免
blur值过大(>8px),优先用4px–6px - 对不支持
filter的老浏览器(IE / iOS @supports (filter: blur(0)) 包裹过渡规则 - 慎用
will-change: filter—— 它可能引发重绘开销,实测多数场景不加反而更稳 - 服务端生成低质量占位图(LQIP)比纯 CSS 模糊更可靠,但那是另一层优化了
真正难的是让模糊态在首帧就稳定出现,而不是靠 JS 加载后才补上——这需要结合 loading="lazy" 的时机、资源优先级和渲染管线节奏,单纯靠 CSS 过渡做不到。


















