SQIP占位图是用少量多边形抽象原图轮廓并叠加模糊的内联SVG,体积小、可缩放、保留构图与主色;不用base64(阻塞渲染)或纯色(缺乏视觉线索),需手动写polygon+filter,控制数量、禁抗锯齿、关动画、匹配尺寸。

直接用 svg 标签内联一个极简的 SQIP 占位图即可,不需要额外库或构建步骤——关键在于控制 path 数量、关闭抗锯齿、禁用过渡动画,并确保尺寸与真实图片一致。
什么是 SQIP 占位图,为什么不用 base64 或纯色
SQIP(SQIP Image Placeholder)本质是 SVG:它把原图用少量多边形(通常 5–20 个)做抽象轮廓 + 模糊叠加,生成极小体积(~1–3 KB)、可缩放、可样式化、可内联的占位图。相比 base64 图片,它不阻塞渲染;相比纯色/渐变占位,它保留了构图和主色调线索,用户体验更连贯。
常见误区是把它当“图片”去 <img src="xxx.svg"> 加载——这样就失去了内联 SVG 的 DOM 可控性,也无法在加载完成前动态替换。
手动写一个可用的 SQIP 占位 SVG(非自动生成)
你不需要跑 Node.js 脚本也能手写一个近似效果。核心是:<svg> + 几个 <polygon> + 一层 <filter> 模糊:
立即学习“前端免费学习笔记(深入)”;
<svg width="300" height="200" viewBox="0 0 300 200" xmlns="http://www.w3.org/2000/svg">
<defs>
<filter id="blur" x="-50%" y="-50%" width="200%" height="200%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
</filter>
</defs>
<polygon points="80,40 220,30 240,160 100,170" fill="#e0d6c9" />
<polygon points="120,80 180,70 190,130 130,140" fill="#b8a99a" />
<polygon points="150,100 170,95 165,115" fill="#8a7a6a" />
<rect width="100%" height="100%" filter="url(#blur)" opacity="0.7" />
</svg>-
viewBox必须与目标图片宽高比一致,否则拉伸失真 - 所有
fill值建议用十六进制(避免命名色在某些 UA 下 fallback) - 模糊用
<feGaussianBlur>,stdDeviation="2"是平衡清晰度与“占位感”的经验值;超过 3 容易糊成一片 - 最后的
<rect>是模糊层,opacity="0.7"防止完全盖住底层文字或背景
如何用 JS 动态替换为真实图片(保持尺寸与位置)
内联 SVG 占位图的优势就在这里:它是 DOM 节点,能被 JS 精确替换而不触发重排。
假设你有一个容器:
<div class="image-wrapper"> <!-- 上面手写的 SVG 占位图 --> <svg>...</svg> </div>
加载真实图片后,用以下逻辑替换:
const wrapper = document.querySelector('.image-wrapper');
const img = new Image();
img.onload = () => {
// 创建 img 元素,复用原始 SVG 的宽高属性
const realImg = document.createElement('img');
realImg.src = img.src;
realImg.width = wrapper.querySelector('svg').getAttribute('width');
realImg.height = wrapper.querySelector('svg').getAttribute('height');
realImg.alt = '描述性文字';
<p>// 替换:移除 SVG,插入 img
wrapper.innerHTML = '';
wrapper.appendChild(realImg);
};
img.src = '/real-image.jpg';- 不要用
innerHTML = '<img ...>'直接拼字符串——会丢失事件监听或破坏已绑定行为 - 务必复用原始
svg的width/height属性,否则图片可能撑开布局 - 如果需要响应式(比如
max-width: 100%),请改用style.width和style.height控制,并在 JS 中同步设置
容易被忽略的兼容性细节
SQIP 占位图在 Safari 15.4 之前不支持 <feGaussianBlur> 的 stdDeviation 小数,设为 2.5 会被截断为 2;IE 完全不支持滤镜。所以生产环境建议:
- 只对现代浏览器启用模糊(可用
@supports (filter: blur(1px))检测) - 降级方案不是显示空白,而是用
fill更密集的<polygon>模拟色块层次,不依赖滤镜 - 如果图片本身有透明区域(如 PNG),SVG 占位图的
<rect>模糊层要设fill="white"并加opacity,否则透出父背景造成视觉跳变
真正麻烦的从来不是生成 SVG,而是让占位图在各种尺寸、DPR、UA 下都“看起来像将要出现的东西”——这需要你盯着它在 iPhone SE、Surface Pro 和 Chrome DevTools 的 device toolbar 里反复调三个 <polygon> 的坐标。



















