也许您听说过数据 URI。这是一种非常好的方式,可以包含原本需要单独 HTTP 请求的资源。您在数据 URI 中使用的格式可能有所不同。本质上,您只需告诉它内容类型是什么(例如 image/png
),分号,然后是该文件的数据。
例如
<img src='data: ... '>
或者
.bg {
background: url('data: ... ');
}
对于像 PNG 这样的光栅图像,该图像的数据需要采用 Base64 格式。我不是这方面的专家,但据我了解,Base64 在 HTML 或 CSS 等内容中使用是安全的,因为它只使用 64 个已知在这些格式中安全的字符。

更好的解释 Stack Overflow 答案 由 Dave Markle 提供
您永远不知道——某些协议可能会将您的二进制数据解释为控制字符(如调制解调器),或者您的二进制数据可能会被破坏,因为底层协议可能认为您输入了特殊的字符组合(例如 FTP 如何转换换行符)。
因此,为了解决这个问题,人们将二进制数据编码成字符。Base64 就是这些编码类型之一。
Base64 看起来像乱码,我们经常将乱码与 Web 上的压缩联系起来。但这种乱码并不是压缩,它实际上比原始数据略大,因为引用 Jon Skeet 在同一 Stack Overflow 线程中的说法
它每 3 个字节的数据需要 4 个字符,加上末尾可能的一些填充。
我不确定 gzip 如何融入其中。但我想说的是 SVG 如何融入其中。
您也可以将数据 URI 用于 SVG。
<img src='data:image/svg+xml; ... '>
.bg {
background: url('data:image/svg+xml; ... ');
}
对于 SVG,您**不必**将数据转换为 Base64。同样,我不是这方面的专家,但我认为 SVG 语法中没有任何疯狂的字符。它就像 HTML 一样,只是 XML,因此在 HTML 中使用是安全的。
您可以将编码保留为 UTF-8,并将 <svg>
语法直接放在那里!像这样
<img src='data:image/svg+xml;utf8,<svg ... > ... </svg>'>
.bg {
background: url('data:image/svg+xml;utf8,<svg ...> ... </svg>');
}
因此,因为我们可以这样做,并且我们知道 Base64 通常会增加大小,所以最好这样做,对吧?是的。作为额外的好处,单独保留的 <svg>
语法可以更好地进行 gzip 压缩,因为它比 Base64 更具重复性。假设您想要两个版本的图标,一个红色,一个黄色。您可以使用相同的 SVG 语法进行复制,只需更改填充颜色即可。Gzip 会将其一扫而空。感谢 Todd Parker 提供此提示,这也是 Grunticon 的方法,它将 UTF-8 中的 SVG 数据 URI 放入 CSS 中。
测试
为了测试这一点,我从 IcoMoon 下载了三个 SVG 图标。

cog.svg – 1,026 字节
play.svg – 399 字节
replay.svg – 495 字节
我通过 SVGO 运行它们,以便它们得到很好的优化并准备好作为数据 URI 使用(空格已删除,尽管我认为这并不是绝对必要的)。
cog.svg – 685 字节
play.svg – 118 字节
replay.svg – 212 字节
然后,我通过 Base64 转换器 运行这些文件。
cog.svg – 916 字节 – 原始大小的 133%
play.svg – 160 字节 – 原始大小的 136%
replay.svg – 283 字节 – 原始大小的 134%
所以这说得通,对吧?如果每 3 个字节有 4 个字符,那么它会大 133%,变化来自不均匀的长度以及填充。
无论如何,也许这一切都非常明显。但在我看来,如果您要将数据 URI 用于 SVG,则没有理由将其 Base64 编码。
感谢 Matt Flaschen 几个月前发送的电子邮件,它让我意识到了这个问题。
更新:关于 IE
评论中有很多关于 IE 10/11/Edge 不支持此功能的讨论。它确实支持,只是有点挑剔。这是一个简化的测试用例,在这些版本的 IE 中可以正常工作。请注意第二个示例,它是 URL 编码的,可以正常工作。诀窍是不指定任何编码类型。
更新:“优化的 URL 编码”
Taylor Hunt 进行了更深入的研究,发现可以通过不编码空格和单引号等内容来进一步优化。例如
data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3E%3Cpath d='M224%20387.814V512L32 320l192-192v126.912C447.375 260.152 437.794 103.016 380.93 0 521.287 151.707 491.48 394.785 224 387.814z'/%3E%3C/svg%3E
并非所有浏览器都支持。据我回忆,Safari 7 和 IE11 不支持。
我认为 URL 编码 SVG 可以解决这个问题,并且尺寸仍然比 Base64 编码更好。
URL 编码?如果您指的是数据 URI 中的文字 XML,那么您建议用问题本身来解决问题。在我提到的浏览器中,这种方法无效。
我的意思是
如果您指的是 Gunnar Bittersmann 在下面建议的字符编码,那可能是解决方案。在使用包含 SVG 的数据 URI 时,我从未想过要尝试这种方法。
是的,我的意思是这个,我之前在 IE 和 FF(那个时候)遇到过这个问题,这两个问题都用这个小技巧解决了。您可能会注意到,uri 编码字符串的原始大小可能大于 Base64,但在 gzip 压缩后,它绝对更小。
是的,需要对 IE 进行 URL 编码确实抵消了简单性。但是,我之前没有想到,如果 URL 编码了多个类似的 SVG,gzip 仍然可以很好地处理它们,但如果 Base64 编码了,则不一定如此。
如果您尚未进入生产阶段,或者正在开发一个不需要 IE 支持的应用程序或其他内容,我整理了一份关于如何在其他浏览器中避免破坏数据 URI 的提示列表。
总结一下其他人所说的以及我刚刚完成的测试
Firefox 4+ 支持 < 和 >,但 # 必须进行 URL 编码
<=IE11 需要完全编码
Chrome 和 Safari 5+ 可以正常工作,无需编码
您的意思是大了 33%,而不是 133%。
在这种情况下,通常使用 Base64,因为它可以避免需要 URL 转义图像,否则就需要这样做。
克里斯,你真的需要上一些数学课……;)
916/685 = 1.33 = 133% = **大了 33%**,而不是 133%。
但是,是的,Base64 可能并不总是好的选择,但 SVG 可能包含不安全的字符(请记住,矢量图像可能包含位图部分……)。此外,像 LESS 这样的工具在您想要数据 URI 时默认将 SVG 作为 Base64 编码……
原始大小的 133%,而不是比原始大小大 133%。
Base64 和纯 UTF8 之间在浏览器支持方面有什么区别吗?我实际上切换到 Base64,因为我听说过其他方法在 IE9 中不起作用(现在找不到来源了)。无论如何,在文章中提及这一点会很好。
克里斯,继续努力——谢谢!
根据RFC 2397,媒体类型中的参数应为属性-值对,即
charset=utf-8
(带连字符!)而不是仅仅utf8
。对于字符编码,data URI 应以data:image/svg+xml;charset=utf-8,<svg
…开头。但是,当使用 UTF-8 时,可以安全地省略编码声明:
data:image/svg+xml,<svg
…根据我的经验,并非所有非 Base64 编码的 SVG 都能在所有浏览器中正常工作。我非常想使用这种方法,但它对我来说一直存在问题。
我想知道这是否是编码与非编码的问题,而不是 Base64 问题。
另一个优点是可以使用 CSS 预处理器的变量来构建 SVG。当然,这会使生成的样式表变得臃肿,特别是如果相同的 SVG 模板以多种不同的方式呈现时。但它确实节省了一个 HTTP 请求,对于导航图标等小型图像很有用。
小心引号!如果您的 SVG 的某个属性包含双引号(“),并且您使用双引号打开/关闭 url() 属性,则直接 SVG 将会出错。单引号也是如此。
如果要使用直接 SVG,则可能需要设置一些预处理来规范化(或转义)引号。
我使用了 Base64(http://www.phoca.cz/cssflags/),因为原始内容在所有“常用”浏览器中都不起作用 :-(。因此,即使 Base64 使内容更大,它也是我唯一的选择 :-(。
不,不是这样。很多人对此理解错误。HTML 不是 XML,并且 HTML 比 XML 早几年出现。
HTML 历史
有趣。
不过,在这个案例中,重点是:尖括号、属性等等,内联 SVG 在 HTML 中运行良好这一事实。它们是同类。
如果有一个 Sass 混合宏就好了。有人见过吗?
看起来 Stack Overflow 上有人创建了一个:http://stackoverflow.com/questions/15454014/url-or-base64-encode-strings-in-compass-sass。将其集成到 Compass 中会很棒。
Less.js 在
data-uri
上有一个可选的mime type
参数。Gunnar 在上面提到的关于媒体类型参数的观点非常重要…
使用简写
data:image/svg+xml;utf8,
会导致 IE10/11 出现错误。使用
data:image/svg+xml;charset=utf-8,
或省略媒体类型似乎可以正常工作。http://codepen.io/RwwL/pen/Aczds
我不确定您是否在说
data:image/svg+xml;charset=utf-8,
在 IE 中有效,但它确实无效。… 使用非编码的 svg。
还有其他人看到 Firefox 中出现类似
的情况吗?更好的是,有人知道解决方法吗?
在将 SVG 放入 data URI 之前,您是否对其进行了 URL 编码?Firefox 需要这样做;查看我上面发布的 Codepen。
你说得对,编码也必须设置为
charset=utf-8
。因为我假设我们都希望继续支持 Firefox,所以我认为这应该在文章中重点突出,并可能用作基准,而不是普通 XML(尽管我相信编码的 XML 仍然会胜出)。Firefox 实际上对“没有问题,它只是不喜欢
#
。在我的测试中,这是唯一需要编码的字符。呃……我上面的评论弄乱了。
“Firefox 实际上对< 和 > 没有问题,它只是不喜欢
#
。”是的,人们确实可以只编写纯 SVG,但它需要对某些符号进行编码,例如引号、‘#’和括号。有趣的是,无需对等号 ‘=’、逗号和 svg 命名空间 URL ‘http://www.w3.org/2000/svg’(因此也无需对斜杠 ‘/’ 进行编码)。IE 需要对尖括号进行编码。空格可以用反斜杠转义:‘\ ’。
但是,有一个技巧可以节省大量字节——使用带引号的 uri:url(“data:image/svg+xml,%3Csvg xmlns=’http://www.w3.org/2000/svg’…%3C/svg%3E”)。然后,无需对空格进行编码或转义,并且可以使用单引号!(但反之则不行。)这非常方便,因为 svg 中充满了这些符号。
我刚刚尝试了一下,注意到 Grumpicon 是如何处理它的
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%...svg%3E');
我对字符编码了解不多,不知道为什么他们使用 US-ACII 而不是 UTF-8。不过,我看到他们确实对括号字符等进行了编码,而不是直接在其中放入 XML。
我确实知道,我通常非常信任 Filament Group 的东西。
您必须对 SVG 语法进行编码,才能在所有浏览器中安全使用。至少 IE 需要这样做。我知道 Chrome 可以直接处理尖括号等,但 IE 不行。因此,他们采取了最安全的方法(对其进行编码),但仍然没有使用 Base64。
尝试将
utf8
更改为charset=utf8
。我设法解决了它。
结果如下
http://codepen.io/verlok/pen/vCwoG
问题是我使用的 URL 编码类型……我从网上选择了一个,但您需要一个实际使用
encodeURIComponent
函数的,例如http://infoheap.com/tool/url-encode-decode-online-tool/干杯!
有趣。当我将您原始笔录中的
utf8
更改为charset=utf8
时,它在 IE 中也运行良好。如果您问我,字符编码是一种奇怪的魔法。我使用此工具获得了更好的结果:http://pressbin.com/tools/urlencode_urldecode/
我在未关闭的引号方面遇到了一个奇怪的问题。我不断收到错误,但发现了一个完全不合逻辑的解决方法。如果有人有想法,请查看 Stack Overflow。
http://stackoverflow.com/questions/27161390/sass-datauris-unclosed-quotes/27161553#27161553
不确定是否有人发布过,但 @Alexis2004 在这里创建了一个不错的 Sass 函数,在将其烘焙到 Compass 构建中之前可以使用:https://github.com/Compass/compass/issues/1460
运行良好,避免使用已经可用的 Compass inline-image() [http://compass-style.org/reference/compass/helpers/inline-data/#inline-image] 进行 Base64 编码。