如何把 SVG 转成 data URI
- 把 SVG 代码粘贴到 文本 框中。用任意文本编辑器打开
.svg文件即可复制代码。文本框里一开始有一个示例图标。 - MIME 类型 已经是
image/svg+xml,编码 已设为 优化的 SVG。 - 查看选项下方的表格。它列出 Base64、URL 编码和优化的 SVG 三种方式的 URI 长度和 gzip 后大小,标出最小的那个,并为每种方式提供一个 使用 按钮。
- 选择 输出格式:原始 Data URI、CSS
url()、HTML<img>、HTML<a>或 Markdown,然后点击 复制输出。
你也可以在 从文件 模式下拖入 .svg 文件,这时可以对文件原样做 Base64 或 URL 编码。优化变体和对比表格需要把代码放在文本框里。
Base64 与 URL 编码 SVG 的大小对比
对于内置示例,一个 309 字节、包含圆角方形、圆和一条线的图标,表格显示:
| 编码 | URI 长度 | gzip 后 |
|---|---|---|
| Base64 | 438 | 337 |
| URL 编码 | 492 | 239 |
| 优化的 SVG | 347 | 220 |
普通 URL 编码的原始长度最长,因为每个空格、引号、<、> 和换行都会变成三个字符。但 gzip 之后它大幅领先 Base64,因为代码保留了重复的结构,而 Base64 把结构打乱了。样式表几乎总是压缩后传输的,所以真正到达用户那里的是 gzip 这一列。
优化的 SVG 在两列中都胜出。对于一个 103 字节的小三角形图标,差距也一样:Base64 166 个字符,URL 编码 172 个,优化版 136 个。SVG 转 Base64 中有对一整套图标的对比。
“优化的 SVG”做了什么
优化器对代码做四处修改:
- 把每一段连续空白(包括换行)合并成一个空格,并去掉首尾空白。
- 把
"替换为',前提是 SVG 中原本没有'。 - 用
encodeURIComponent做百分号编码,再把在 URI 中安全的字符还原:空格、=、:、/、,和;。 - 把剩下的转义写成小写(
%3c而不是%3C),这样 gzip 效果略好:示例为 220 字节,而不是 222 字节。
三角形图标的结果:
data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath d='M8 1 15 15H1z' fill='%23e33'/%3e%3c/svg%3e
颜色中的 # 变成了 %23。这个转义是必需的:未转义的 # 会开始一个 URL 片段,后面的所有内容都会被悄悄丢弃。
引号和上下文规则
优化后的输出包含单引号、原始空格和原始括号,放在双引号里没问题,放在其他地方就不行:
.icon { background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' ...%3e"); }
<img src="data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' ...%3e" alt="">
不加引号的 url(...) 会在空格处断开,单引号属性会在第一个 ' 处结束。如果 URI 是在 JavaScript 中拼接的、由模板引擎插入的,或者要粘贴到会改写引号的系统里,Base64 更稳妥:它只包含字母、数字、+、/ 和 =,在任何上下文中都不会出问题。用表格中的 使用 按钮切换即可。
其他限制都不大。优化的 SVG 始终为 UTF-8,会忽略你选择的其他字符集,并给出警告。合并空白可能会改变保留空格的 <text> 元素中的文字。另外,和所有作为图片使用的 SVG 一样,根元素上仍然需要 xmlns="http://www.w3.org/2000/svg"。
用 JavaScript 实现优化器
同样的转换几行代码就能写完,适用于构建脚本或 CSS-in-JS:
function svgToDataUri(svg) {
let s = svg.trim().replace(/\s+/g, " ");
if (!s.includes("'")) s = s.replaceAll('"', "'");
const keep = { "%20": " ", "%3D": "=", "%3A": ":", "%2F": "/", "%2C": ",", "%3B": ";" };
return "data:image/svg+xml," + encodeURIComponent(s)
.replace(/%[0-9A-F]{2}/g, m => keep[m] || m.toLowerCase());
}
它生成的就是上面那个三角形 URI。关于在浏览器和 Node 中编码的更多内容,见 JavaScript 中的 Base64。要读取现有的 SVG data URI,把它粘贴到 Base64 转 SVG 或 Data URI 解析器。
常见问题
把 SVG 放进 data URI,最短的方式是什么?
通常是优化后的 URL 编码:合并空白、把双引号换成单引号,并且只转义必须转义的字符。示例图标用这种方式是 347 个字符,而 Base64 是 438 个。
为什么 URL 编码的 SVG 会让 CSS 出错?
最常见的原因是引号冲突。优化后的输出内部使用单引号,所以外面必须用双引号:url("data:image/svg+xml,...")。颜色值里没有转义的 #(比如 #f00)也会把 URI 截断,它必须写成 %23。
优化编码会改变 SVG 的显示效果吗?
对普通图形不会。它只合并空白并替换引号样式。带 xml:space="preserve" 或 CSS white-space 规则的 <text> 中的文字,可能会丢失多余的空格。
SVG data URI 需要加 ;charset=utf-8 吗?
不是必需的。SVG 是 XML,除非文件声明了其他编码,否则 XML 会按 UTF-8 读取,所以带重音字母的标签不加它也能正常显示。字符集 默认为(无);选择 UTF-8 会多出 14 个字符,但没有坏处。