图片模糊到清晰效果需容器占位、模糊类初始激活、加载完成移除三步闭环,缺一不可;直接对img加blur-md常因内联显示、无高度、onload不触发等原因失效。

直接用 blur-md 类不会让图片“自动模糊占位”——它只是设置 filter: blur(4px),而浏览器对未加载图片的渲染行为不一致,往往导致模糊态压根没机会显示。真正在加载前看到模糊效果,得靠「容器占位 + 模糊类初始激活 + 加载完成移除」三步闭环。
为什么 img 加 blur-md 常常无效
常见现象:图片一闪就清晰,或根本没模糊过渡。原因很实在:
-
<img>默认是内联元素,部分 Safari 和旧版 Chrome 对内联元素的filter过渡支持不稳定,必须加display: block - 图片
src是本地路径或 data URL 时,浏览器可能跳过加载流程,onload不触发,模糊类永远不被移除 - 没设宽高约束,
blur作用在 0×0 区域上,视觉不可见;尤其在 flex/grid 容器里,img高度塌陷,滤镜无处生效
必须提前撑开容器空间:用 aspect-ratio 或 padding-top hack
加载前容器高度为 0,blur 就像往空气里打滤镜——看不见也过渡不了。撑开空间不是可选项,是前提。
- 现代写法:
div容器设aspect-ratio: 16 / 9(或你图片的实际比例),再套img并配width: 100%; height: 100%; object-fit: cover - Safari ≤15.4 兼容降级:用
position: relative+padding-top: 56.25%(16:9)+min-height: 0.01px防 Safari 忽略百分比 - 别只靠
max-width: 100%—— 它只管宽度,不管高度;没高度,blur就没渲染区域
模糊类要作用在容器上,且不能被硬件加速禁用
把 blur-md 直接写在 <img> 上看似合理,但容易踩坑:
- 如果父容器用了
transform或will-change: transform,某些浏览器会禁用filter的硬件加速,导致模糊动画卡顿甚至失效 - 更稳妥做法:把
blur-md加在包裹<img>的div上,同时确保该容器有明确尺寸(aspect-ratio或padding-top已撑开) - 移动端慎用
blur-xl(>8px)—— iOS WebKit 会自动降级为均值模糊,且不触发transitionend,建议上限设为blur-md(4px)
用原生 onload 移除模糊,别依赖 CSS :has()
:has(:loaded) 目前仅 Safari 支持,Chrome/Firefox 仍不兼容。最轻量、最可靠的方案就是原生事件:
- 初始 HTML:
<div class="relative aspect-[16/9] blur-md transition-all duration-500"><img src="high.jpg" onload="this.closest('div').classList.remove('blur-md')"></div> - 防加载失败降级:
onerror="this.closest('div').classList.add('opacity-70')" - React/Vue 中别在
useEffect或mounted里手动监听load—— 原生onload更早触发、更稳定
真正难的不是写几行 blur,而是让模糊出现在「加载前那一帧」——这要求容器空间、元素 display 类型、事件触发时机、硬件加速策略全部对齐。少一个环节,效果就断在半路。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











