一、Data URL 的写法
.icon {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...");
}
<img src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0i..." alt="logo" />
格式是 data:[MIME类型];base64,[数据]。浏览器看到 data: 就直接解码渲染,不发 HTTP 请求。
二、三个必须算清楚的数字
| 项目 | 影响 |
|---|---|
| 体积 | Base64 后约 +33%(3 字节变 4 字符) |
| 缓存 | 内联后跟随所在文件缓存,改一个图标会让整个 CSS 失效 |
| 解析 | 图片数据进入 HTML/CSS 主文件,阻塞首屏渲染,且无法并行下载 |
也就是说:省下的是「请求数」,付出的是「体积 + 缓存粒度 + 渲染阻塞」。在 HTTP/1.1 时代请求开销大,这笔交易常常划算;在 HTTP/2、HTTP/3 多路复用下,请求本身已经很便宜,收益明显下降。
三、什么情况适合
- 小于 2–4KB 的图标、logo、 loading 占位图。
- 需要「单文件分发」的场景:一份 HTML 报告、一封邮件模板、离线文档。
- 图片必须和页面同源、又不想配静态资源服务时。
- 需要避免额外请求的极小装饰元素(分隔线、圆点)。
四、什么情况不适合
- 照片、商品图、banner(几百 KB 起步)。
- 会在多个页面复用的图(内联等于重复传输)。
- 需要被 CDN 单独缓存、单独更新的资源。
- 需要响应式
srcset的图(内联后没法按屏幕切不同尺寸)。
一张 100KB 的 JPEG 转成 Base64 约 137KB,如果它出现在 10 个页面里,用户就要多下载 370KB,而且每个页面的 HTML 都变大。这种情况下「少一次请求」完全是负收益。
五、几个实操细节
- SVG 建议用 URL 编码而不是 Base64:
data:image/svg+xml,%3Csvg...体积通常更小,且可读。Base64 反而会变大。 - 换行:部分工具生成的 Base64 每 76 字符带换行,粘进 CSS 会报错,需去掉空白。
- MIME 类型要写对:
image/jpeg写成image/jpg某些浏览器不认。 - 构建期处理:现代打包工具(Vite/webpack)可配置
assetsInlineLimit,小于阈值的资源自动内联,这是最省心的做法,不用手工转。 - 隐私:转 Base64 不改变图片内容,EXIF 里的 GPS 信息依然在。要分享出去前先清除,见 图片 EXIF 去除。
六、一个折中方案
图标类资源合并成 SVG sprite 或图标字体,比逐个 Base64 更省体积、也能被缓存;真正需要内联的只留首屏那几个关键小图。判断标准是:这张图会不会在别的页面重复出现——会,就别内联。
需要临时转换或还原时,用 图片转 Base64;如果目标是减小体积而不是内联,直接用 图片压缩,先缩尺寸再降质量,效果比编码方式的选择大得多。
小结
Base64 内联省请求、增体积、坏缓存。小于 4KB 且不复用的图标可以用,大图和复用图不要用;SVG 优先 URL 编码;构建工具设个阈值自动处理最省事。