SVG sprite 是将多个 SVG 图标合并到一个 <svg> 容器中,用 <symbol> 按 id 区分、再通过 <use> 引用的 DOM 复用技术;不用 <img> 是因其每个图标触发独立 HTTP 请求,且无法用 CSS 修改内部样式(如 fill)、不支持缩放无损和样式上下文共享。

SVG sprite 是什么,为什么不用 <img> 直接引用单个 SVG
SVG sprite 本质是把多个 SVG 图标合并进一个 <svg> 容器,用 <symbol> 按 id 区分,再通过 <use> 引用。它不是图片文件拼接,而是 DOM 内部复用——所以不产生额外 HTTP 请求,缩放无损,支持 CSS 控制颜色/大小,还能避免重复解析 SVG 结构。
直接用 <img src="icon.svg"> 看似简单,但每个图标都是一次请求;且无法用 CSS 改变内部 fill,也不能和页面其他 SVG 共享样式上下文。
手动生成 SVG sprite 的关键步骤和易错点
核心是:所有源 SVG 必须剥离冗余属性(如 width/height/viewBox 保留但需统一),确保 <symbol> 内部只含路径、组等绘图元素,不含 <defs> 外部定义(否则 <use> 可能失效)。
- 用脚本或手动清理每个 SVG:删掉
<svg>根标签,保留内部<path>、<g>,补上统一viewBox="0 0 24 24"(按你设计规范定) - 合并时每个图标包进
<symbol id="icon-home">...</symbol>,id命名避免特殊字符和空格 - 最终 sprite 文件以
<svg xmlns="http://www.w3.org/2000/svg" style="display:none">开头,防止意外渲染 - 别把
<style>或<script>塞进 sprite——它们不会被<use>继承,还可能触发 CSP 报错
在 HTML 中安全引用 sprite 里的图标
最稳妥方式是把 sprite 文件内联进 HTML 的 <body> 底部(或 <head>,但需加 style="display:none")。这样 <use> 才能跨作用域引用。
立即学习“前端免费学习笔记(深入)”;
引用写法必须带完整 xlink:href(旧浏览器)和 href(新标准),例如:
<svg class="icon"> <use href="/sprite.svg#icon-search" xlink:href="/sprite.svg#icon-search"></use> </svg>
注意:/sprite.svg#icon-search 是外部文件路径,如果 sprite 是内联的,应写成 #icon-search;但 Safari 12–15 对内联 <use href="#xxx"> 有缓存 bug,建议始终用绝对路径或确保 sprite 在 DOM 中已就绪。
- 别用
<object>或<iframe>加载 sprite——<use>无法跨文档引用 - CSS 控制尺寸时,优先设
<svg class="icon">的宽高,而不是改<use>——后者不生效 - 需要动态换图标?改
<use>的href属性即可,但记得同时更新xlink:href保持兼容
自动化构建时怎么避免路径和 ID 冲突
用 Webpack 的 svg-sprite-loader 或 Vite 插件(如 vite-plugin-svg-icons)能自动处理,但默认配置容易翻车:
-
svg-sprite-loader的extract设为true会生成独立 sprite 文件,但若多个入口都 import SVG,可能生成重复 ID —— 需配symbolId: 'icon-[name]'统一前缀 - Vite 插件默认把所有 SVG 当图标处理,如果你项目里有作为图片使用的 SVG(比如 banner 图),得用
include显式限定目录,例如include: ['src/icons/**/*.svg'] - 构建后检查最终 sprite 文件:确认没有两个
<symbol id="xxx">重复,且每个id在整个 HTML 页面中唯一(包括其他 JS 动态插入的 SVG)
ID 冲突不会报错,但会导致 <use> 随机显示错误图标——这是线上最难排查的 SVG 问题之一。


















