临时占位图需满足不发请求、不破布局、不藏bug、易切换四大原则;纯css渐变最轻量,真实小图适用于懒加载,onerror须防循环,holder.js仅限开发,必须配合宽高比容器防重排。

临时占位图片资源不是“随便放个灰块就行”,关键在于:不发请求、不破布局、不藏 bug、能快速切换或移除。纯 CSS 方案最稳,JS 控制要防循环,路径和格式必须可控。
用 CSS 渐变代替图片文件最轻量
本地占位图(如 placeholder.png)看似简单,但每次加载都会触发一次 HTTP 请求——离线时失败,CDN 故障时空白,CI/CD 环境里还可能因路径未同步导致 404。用 linear-gradient 完全规避这些问题:
-
background: linear-gradient(#e0e0e0, #e0e0e0)必须写两个相同颜色,否则 Safari 15.2 及更早版本会渲染成透明 - 配合
background-size: 320px 240px(按目标图宽高设),否则容器会被拉伸或裁切 - 加
background-repeat: no-repeat,否则渐变会在小容器里平铺出条纹感 - 若父容器有
padding,加background-origin: content-box,让渐变从内容区左上角起始
懒加载场景下占位图必须是真实小图
当用 IntersectionObserver 或 loading="lazy" 延迟加载时,src="" 或 src="data:image/gif,..." 在部分 Android WebView 中会解析失败,导致空白;而纯 CSS 渐变无法被 JS 检测为“已加载完成”。此时必须用真实存在的小图:
- 尺寸与目标图完全一致(如 750×500),格式为 PNG(支持透明,体积可控)
- 文件大小压到 1–2 KB,可用 TinyPNG 批量处理
- 路径写相对路径,且统一从 HTML 文件所在目录出发(避免混用
./images/和images/) - JS 加载真实图后,务必显式重置
src并移除lazy类,否则 IntersectionObserver 可能重复触发
onerror 降级不能只靠 this.src = 'fallback.png'
直接写 onerror="this.src='fallback.png'" 是常见陷阱:如果 fallback.png 也加载失败,就会无限循环触发 onerror,最终卡死。更糟的是,它对跨域图片静默失效(未设 crossorigin 属性时):
- 正确写法:
onerror="if (this.src !== '/fallback.png') this.src = '/fallback.png';" - fallback 图建议用 base64 内联 SVG(如
data:image/svg+xml;base64,PHN2Zy...),彻底规避网络请求 - 不要指望
onerror捕获background-image失败——那是 CSS 层面问题,需另配媒体查询或 JS 检测 - 现代项目中,
onerror+loading="lazy"在 Safari 上行为不稳定,建议降级逻辑改用load+error事件监听器组合
Holder.js 仅适合开发阶段预览
Holder.js 动态生成占位图看着方便,但它依赖 JS 执行、会插入额外 DOM 节点、不兼容 CSP 严格策略,线上环境容易成为性能和安全盲点:
- 开发时可全局启用:
Holder.run({ images: '600x400' }),但上线前必须删掉 script 标签和所有data-src占位语法 - 它生成的占位图没有
naturalWidth,无法用于 layout shift 检测或 CLS 计算 - 若用在 SSR 场景(如 Next.js),服务端渲染时 Holder.js 不执行,首屏仍是空白或 fallback
- 真正需要动态占位的生产环境,应优先考虑 LQIP(低质量图像占位):用模糊 base64 图嵌入
background-image,再通过 JS 替换为高清图
最易被忽略的一点:所有占位方案都必须配合 aspect-ratio 或宽高比容器(如 height: 0; padding-bottom: 56.25%),否则图片加载前盒模型塌陷,文字上推重排——这不是视觉问题,是浏览器强制重绘,无法靠 CSS 动画掩盖。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











