这个页面的代码没跑起来。

直接从文件夹里打开 index.html,浏览器会拦下 JavaScript 模块,于是你选好图片之后,页面不会有任何反应。改用 http 把这个文件夹提供出去:

powershell -ExecutionPolicy Bypass -File serve.ps1

然后打开 http://localhost:8080/。

图片转 Data URI 图片 base64 编码,给 CSS 和 HTML 用

整张图变成一行文本,直接粘进 CSS 或者 HTML。

语言: 简体中文
查看源码
你的图片在浏览器里处理,无须上传处理。

编码在你自己的浏览器里、用你自己的硬件完成。它就是对页面手上已有的字节做算术,没有编码器,没有服务器,也没有哪一步联网可以省。这个工具没有任何联网功能,不取东西,也不发东西。就算真有,这个页面的另一头也没有服务器能接住一张图。

实时检查: 检查中…

离线: 检查中…

别信我们嘴上说的。打开开发者工具,盯着“网络”面板,丢一张图进来。没有一条请求带着图片、缩略图、文件名,或者你选中内容里的任何一个字节。或者干脆拔掉网线,照编不误。

1 选图片

2 说清楚它要粘到哪儿

光给一串 data URI,其实很少有人真想要。大家要的是能直接贴进样式表的那一行。所以先挑好这一行的样子,图片进去时引号已经加好了。引号这东西最容易弄错,偏偏还只有 SVG 会因此出事。

alt 是故意留空的。这张图到底有实际含义还是纯装饰,只有你知道。拿文件名瞎猜一句描述,对用读屏软件的人来说,比没有描述更糟。

XML 编码不是 UTF-8 或包含无效 UTF-8 字节的 SVG 会自动使用 base64,保留原始字节和编码声明。

SVG 也用 base64 默认关着,因为 SVG 是文本,而 base64 是给字节用的。百分号编码能让标记在样式表里还看得懂,通常还短五分之一。个别工具链非要 ;base64 不可,才把这个打开。

SVG

3 复制

还没选东西。往上面丢一张图,能粘出去的那一行就出现在这儿。

以 Markdown 查看

图片怎么转成 data URI

  1. 选好你的图片。拖到下面的方框里,或者点开自己挑。浏览器直接从你的硬盘上读,这期间没有东西发出去。
  2. 说清楚这行要粘到哪儿。光要 URI,要一条 CSS 规则,要一个自定义属性,要 <img> 标签,还是要 Markdown。每一种都替你把 URI 的引号加好了,而引号正是最容易弄错的地方,弄错了偏偏只有 SVG 会出事。
  3. 看看代价有多大。每个结果都写明它变成了多少个字符、比原文件大出多少,以及这么大的东西内联进去到底合不合算。base64 会多出三分之一,这三分之一值不值一次省下的请求,完全看文件多大,所以页面直接告诉你落在界线的哪一边。
  4. 看一眼那些提醒。图片要是带着 EXIF、色彩配置文件或者 XMP,页面会点名,并算出你这串结果里有多少字节是它们。扩展名跟实际格式对不上时,按实际格式来,并告诉你一声。浏览器画不出这个结果,它也会直说。
  5. 复制,或者下载。每个结果一个按钮,另外还有一个把全部结果一次拿走。选自定义属性时,输出外面已经套好一个 :root 块,粘到样式表开头就能用。

说得更细的版本

什么时候该把图片塞进 CSS,什么时候不该 data URI 的代价在哪儿,base64 为什么多出三分之一而 gzip 又还不回来,SVG 为什么绝不该用 base64,以及那个只坑内联 SVG、还一声不吭的引号问题。

常见问题

我的图片会传到什么地方去吗?

不会。读取和编码都由你自己的浏览器在你自己的硬件上完成,用的是浏览器早就有的两个函数。这个工具没有任何联网功能,不取东西,也不发东西。页面的 Content-Security-Policy 把它可能联的地址全列了出来,没有一个是本站的。

data URI 是什么?

一种把整个文件写在“本该写网址的地方”的办法。原来写 url("logo.png"),浏览器就得跑一趟去取;改写成 url("data:image/png;base64,iVBORw0..."),图片本身就在这串字里,浏览器当场解出来。实际效果是少一次请求,图片跟着样式表或者页面一起到,而不是等它们到了之后再去取。

为什么我的 SVG 没走 base64?

有效的 UTF-8 SVG 使用可读的百分号编码,通常比 base64 更短。采用其他 XML 编码或包含无效 UTF-8 的 SVG 会自动使用 base64,保留原始字节和编码声明。勾选复选框也会让 UTF-8 SVG 使用 base64。预览仍取决于浏览器能否绘制原始文件。

base64 会让图片大多少?

大约三分之一。三个字节的文件变成四个字符的 base64,也就是 33%,前面还要再加上 data:image/png;base64, 这一截。这是底线,躲不掉,用网址允许的那些字符去表示任意字节,代价就是这么多。也正因如此,页面把字符数摆在文件大小旁边,省得你等样式表都发布了才发现。

什么时候内联图片才真的划算?

又小又必须马上出现的时候。每个页面都要加载的样式表里放一个 2 KB 的图标,这是明摆着的赚:少一次往返,CSS 一到图就在。过了大约 10 KB,这笔账就翻过来了。内联进去的图片不再是一个独立文件,没法单独缓存,没法跟别的东西并行下载,而且外面那个文件一改,它就得整个再下一遍。样式表里塞一张 200 KB 的照片,等于给全站每个页面的关键路径都加了 200 KB。每个结果落在界线的哪一边,页面会告诉你。

gzip 能把 base64 多出来的那部分压回去吗?

没大家想的那么灵。base64 编的要是本来就压过的文件,PNG、JPEG、WebP 都是这种,压出来效果很差,因为里头几乎没有冗余留给压缩器去找了。通常也就找回 base64 多出来那三分之一里的十分之一,绝不是全部。百分号编码的 SVG 正好相反,它还是文本,压缩效果跟原来差不多,这也是不该给 SVG 上 base64 的又一个理由。

这一步会动我的图片吗?

不会,而且这一点跟这里多数工具是刻意不同的。没有哪一步把它解码成像素再编回去,从你硬盘上读出来的字节,就是进 URI 的那些字节。JPEG 还是原来那个 JPEG,画质一样,尺寸一样。也正因为如此,结果可以说就是同一个文件,而不是它的一份副本。

那 EXIF 和 GPS 也一起进样式表了?

是的,而这正是粘出去之前值得想一想的地方。因为什么都不重新编码,相机写下的东西全都跟着画面走:位置、时间戳、机身序列号。手机照片里这些能占到 30 KB,编成 base64 就是 40 KB 压在你页面的关键路径上,同时还把一个家庭住址提交进了仓库。JPEG、PNG 和 WebP 里到底带了多少元数据,页面会读出来告诉你。想先清干净,用 EXIF 查看与清除。

为什么它用的类型跟我的扩展名不一样?

因为扩展名可能是错的,字节不会。一个叫 logo.png、其实是按 JPEG 导出的文件,常见到每个图片工具都得应付。而一个类型声明错了的 data URI 根本不显示,没有兜底,也没有一句值得看的报错。所以类型是从文件开头那几个字节读出来的,这里涉及的每种格式,开头都说得毫不含糊。两边对不上时,页面会告诉你。

预览是空白,哪儿出问题了?

多半不是 URI 的问题。HEIC 和 TIFF 都能生成完全合法的 data URI,可除了 Safari 没有浏览器画得出来,所以你粘到哪儿它就在哪儿缺一块。先用图片压缩或者图片缩放转成 PNG、JPEG 或 WebP 再说。要是格式本来就很普通,那多半是文件本身坏了:预览是拿这个页面生成的 URI 画的,画不出来,就说明这张图没能解码。

data URI 有长度上限吗?

有。浏览器对数据 URL 有有限的大小上限,各实现不同;目标应用或内容策略可能设置更小的上限。CSS 和 <img> 可以使用数据 URL,但地址栏导航另有安全限制。请保持内嵌图片较小,并在使用位置测试。MDN 说明了相关上限和限制。

免费吗?要注册吗?

免费,没有账号,不用登录,没有试用期,也没有水印。文件的数量和大小同样没有上限,因为没有哪台服务器在为它们掏钱,活是在你自己的机器上干的。本站带广告,经费就是这么来的,广告拿不到关于你图片的任何信息。

断网能用吗?

能。页面开一次之后断网,它照干不误。这也是证明“什么都没上传”最省事的办法。一个把图片送出去编码的工具,拔线那一刻就停了。