您是否知道,在 HTML 中使用 <img>
元素或在 CSS 中声明背景图像时,无需链接到外部图像文件?您可以使用**Data URI**将图像数据直接嵌入文档中。
(说“Data URL”也同样正确,我个人更喜欢这种说法。)
使用 CSS,它看起来像这样
li {
background:
url(data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7)
no-repeat
left center;
padding: 5px 0 5px 25px;
}
使用 HTML,它看起来像这样
<img src="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7" alt="star" width="16" height="16">
具体格式如下
data:[<mime type>][;charset=<charset>][;base64],<encoded data>
基本上是一长串乱七八糟的字符。当然,对于浏览器来说,它并不是乱码。这些数据被解释为您所声明的文件类型。
您可以在此处查看一个非常简单的演示页面。接下来我将介绍重要的部分。
为什么要这样做?
最大的原因:它可以节省 HTTP 请求。除了纯文档大小外,这是影响页面加载速度的首要因素。越少越好。
如何获取代码?
使用此在线转换工具。这是我发现的最好的一个。还有一个拖放工具。
另请注意,base64 并不是 Data URI 的唯一可能格式,有时它甚至不是一个好主意。ASCII 是另一种格式,其中代码本质上是 URL 编码的,或者 UTF-8。
浏览器兼容性
Data URI 在 IE 5-7 中不起作用,但在 IE 8 中受支持。您可以
- 使用仅限 IE 的样式表来放置图像,或者,
- 仅将其用于渐进增强类型的内容,在这些内容中,没有图像是可以接受的,或者,
- 不关心
- 阅读这篇文章,了解一种确实有效的替代技术。
重要说明
- 嵌入代码的大小略大于资源本身的大小。GZip 压缩将有所帮助。
- IE8 的最大 Data URI 大小最低为 32768 字节。(嘿?!那个奇怪的数字又出现了。)
- 对于所有内容都嵌入 Data URI 的网站,很难进行维护。更新图像并替换它更容易。
- 如果您使用的是 PHP(或将 PHP 用作 CSS),您可以像这样动态创建 Data URI:
<?php echo base64_encode(file_get_contents("../images/folder16.gif")) ?>
- 您应该仅在缓存频繁的文档中使用此方法,例如您的 CSS 应该缓存。如果 CSS 文件可以节省 6 个 HTTP 请求,那么它的大小为 300k 而不是 50k 是可以接受的,但这仅在 CSS 文件的缓存效果与这些图像一样好的情况下才成立。在 CSS 文件上设置较长的过期时间应该会有所帮助。
- Data URI 不限于图像,它们实际上可以是任何东西。
- 当
<canvas>
获得更多支持并且人们为其构建了很酷的工具时,它可能会使所有这些变得过时。 - Compass有一个辅助函数。
关于性能
……在衡量数十万个移动页面浏览量的性能时,使用 Data URI 加载图像的平均速度比使用二进制源链接(例如带有 src 属性的 img 标签)慢 6 倍!
“如果 CSS 文件可以节省 6 个 HTTP 请求,那么它的大小为 300k 而不是 50k 是可以接受的。” 嗯,它确实节省了 6 个请求,页面加载速度也会更快,但用户将不得不等待 CSS 下载才能看到一些视觉反馈。
您可以在此处查看示例 – http://stevesouders.com/cuzillion/?c0=hc1hfff10_0_f&c1=bi1hfff2_0_f&t=1269523975920
浏览器(Opera 除外)正在等待,否则它将不得不渲染两次。
您可以使用多个样式表,一个用于所有 css 代码,另一个用于图像!?
这很酷。如果您如上所述使用 PHP,您可能可以编写一个非常快速的函数来检查正在使用的浏览器(即 IE6),然后决定是编码文件路径还是使用常规 img 标签。
这听起来像一个非常好的主意,您可以先让 php 解析 css,然后检查浏览器,并根据它输出数据或图像的 url。
这与缓存相结合应该是一个非常好的方法……
我喜欢这个东西。谢谢!
如果您曾经创建过一个单页 Web 文档并将其通过电子邮件发送给其他人而不是上传到服务器,那么这将非常有用。我想到的最佳示例是简历或类似的东西。
我以前用过这个,它可以避免为该单个文档发送一堆文件的麻烦。相反,您只需发送“my-resume.html”即可完成。
如果您想在实时网站上使用它,我建议仅用于非常小的图像(例如列表项目符号),因为正如 Jason Zhekov 发布的示例所示,它可能会导致非常长的加载时间。
您的论点无疑是有效的,但是
images/pretty-flower.jpg 或 images/me-after-way-too-much-beer.jpg 在我必须浏览代码时会更清晰……
“我必须浏览代码” – 那里有一些错别字 – 试图用 me-after-way-too-much-beer 图像告诉我们一些事情哈哈?
此 W3C 规范规定
img
元素应始终具有alt
属性,以及何时“必须”为属性提供值的列表。当按您描述的方式使用时,备用文本不应为空,这将使其易于记录和稍后确定图像的内容。今天在我的 RSS 订阅源中弹出这一点很有趣。我刚刚权衡了在 hcard 中使用 data uri 的选项。
这对于小图像(例如图标)以及页面的移动版本非常有用
您应该仅对每个页面或使用最频繁的页面上的元素使用此方法。如果您不这样做,用户将加载“图像”,即使他们不必这样做。
有关 Data URI 的进一步说明,请查看此页面:http://www.nczonline.net/blog/2009/10/27/data-uris-explained/
老实说,我以前不知道这也能实现。在如今网络速度飞快的时代,对于一个设计良好且代码规范的网站来说,这似乎没有必要。也许是我孤陋寡闻,但真的看不出这在现实中能产生多大影响。
不过,感谢你实现了它并向我们展示了它是如何工作的。你的代码总是让我惊叹不已。
谢谢。
如果这方法很好,它早就成为普遍做法了。
那IE6 怎么解释呢?
David Desandro 有一个很棒的工具,可以使用 <canvas> 元素创建 Data URI。他建议使用 canvas 以程序方式生成图形,然后将 URI 直接插入 CSS。如果您擅长图形编程,这对于原型设计非常有用。
缓存怎么办?当您引用图像时,它只会被加载一次,并且无论何时您浏览该网站,都会从缓存中加载图像。当您在 HTML 中“硬编码”它时,每次都会加载它……(流量更大且速度更慢)
理想情况下,您应该将此硬编码到外部样式表中,而不是 HTML 中,这样它仍然会被缓存。
是的,data uri 很棒。我在开发 iPhone 网页应用时使用它。在这种情况下,它特别有用,因为您不必担心 IE,并且可以更轻松地处理应用缓存。
Data URI 可以用在 CSS 雪碧图中吗?怎么做?
我看不出为什么不行,只需将 background-image 设置为 data URI 并根据需要更改定位即可。
我想知道苹果是否就是用这种方式发送 HTML 邮件,从而在其他公司需要我“点击批准”才能显示图片时,我的邮件可以无问题地显示图片。
好问题!绝对值得探索。
一定是这样。我一直想知道他们是怎么做到的,更重要的是,为什么其他公司不做同样的事情。
我今天收到了一封来自苹果的邮件,它要求我批准图像……
创建 HTML 邮件时,您可以选择是否嵌入图像。嵌入的优点是您的邮件(可能)会按预期显示。缺点是邮件更大,如果您要发送大量邮件,这可能是一个问题。此外,当电子邮件客户端从您的服务器请求图片时,您错过了跟踪机会。
@andy:可能,您曾经批准过从苹果服务器下载图片是“安全的”,并且您的电子邮件客户端会记住这一点。
这看起来比引用 MIME 附件来嵌入图像容易多了。
如果您查看包含嵌入图像的电子邮件的源代码,它看起来像这样
然后稍后,图像将成为具有匹配 ID 的 MIME 附件
------=_NextPart_000_02A7_01CAC9B2.32C8E9F0
Content-Type: image/jpeg;
name="image002.jpg"
Content-Transfer-Encoding: base64
Content-ID
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIf...
(这是由 Thunderbird 生成的,显然您可以使用更简单的 cid 值)
此方法可以在不要求用户点击“显示图片”的情况下传送图片丰富的电子邮件,但手动操作很麻烦。例如,如果您正在编写订单确认脚本,并且希望使用公司徽标和背景图像使收据看起来更漂亮,则此方法看起来比构建 MIME 附件容易多了。
感谢“技巧”Chris!
这看起来比引用 MIME 附件来嵌入图像容易多了。
如果您查看包含嵌入图像的电子邮件的源代码,它看起来像这样
<code>
<img width=3D703 height=3D413 =
id=3D”Picture_x0020_10″
src=3D”cid:[email protected]″>
</code>
然后稍后,图像将成为具有匹配 ID 的 MIME 附件
<code>
——=_NextPart_000_02A7_01CAC9B2.32C8E9F0
Content-Type: image/jpeg;
name=”image002.jpg”
Content-Transfer-Encoding: base64
Content-ID: <[email protected]>
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIf…
</code>
(这是由 Thunderbird 生成的,显然您可以使用更简单的 cid 值)
此方法可以在不要求用户点击“显示图片”的情况下传送图片丰富的电子邮件,但手动操作很麻烦。例如,如果您正在编写订单确认脚本,并且希望使用公司徽标和背景图像使收据看起来更漂亮,则此方法看起来比构建 MIME 附件容易多了。
感谢“技巧”Chris!
真是个好点子,我得试试这个。
嗯,有点像,但又不完全一样。
基本上,所有电子邮件附件,包括图像,都有一个标题,指示附件的内容类型、长度、字符集(ASCII、UTF-8 或某些过时的字符集)和编码(对于二进制文件,通常为 base64)。您还可以为附件分配一个内容 ID,可以在 HTML 中引用它。
<img src="cid:yourContentId" />
当然,这仅适用于电子邮件和其他多部分格式。在这种情况下,您的 HTML 只是另一个附件。使用 cid: 方案在独立 HTML 中没有意义。
您可以右键点击苹果邮件中的图片,看看是不是这样。
这引出了另一个要点……您无法轻松地将 data URI 图像从浏览器拖放到外部保存(至少在 Firefox 中是这样),因此这是一种基本的图像保护形式。不过,您可以右键点击“另存为”……
您可以随时禁用鼠标右键。
这不是因为他们将自己添加到您 Mac 上的通讯录中,并且通讯录中的人的图片会自动加载吗?
我之前以为是这样……不过也许不是。
Google 在 Gmail 的移动版中使用了这种技术,将您的用户代理更改为移动设备,例如 iPhone,然后访问 gmail.com。
他们主要将其用于 Google 徽标和 Buzz 图标,这只是使出色的**单个 HTTP 请求**移动版 Gmail 的众多技巧之一。
Chris,
感谢您帮助传播 data URI 的福音!
您可能还想包含两个资源链接……
一个很棒的基于 Web 的工具,提供了许多在样式表中嵌入 data URI 的选项
http://duris.ru/
Nicholas Zakas 用于在样式表中嵌入 data URI 的命令行工具
http://www.nczonline.net/blog/2009/11/03/automatic-data-uri-embedding-in-css-files/
此外,对于好奇的人,我写了一些关于不同用例场景和需要注意的潜在问题的帖子。其中一篇文章
http://www.ravelrumba.com/blog/data-uris-for-css-images-more-tests-more-questions/
嘿 Chris,如果这是一个愚蠢的问题,请原谅……回复中的蓝色背景是什么意思?
这意味着该评论被“推荐”,因为我认为它特别有趣。这种样式可能不会永远保留……我最终希望用更酷的东西替换它……
金星会更有意义。
很酷!不要引用我的话,但我认为这种方法在 IE 和 HTTPS 请求中存在一些问题。出于某种原因,如果对图像使用编码,则会出现“此页面上的某些元素不安全”对话框。
我可能错了,也可能仅限于 IE7。
1. 语义内容:那就不重要了,呵呵。
2. SVG – 比 XHTML 更好的主意:习惯使用它。
3. Data URI:当现在建议您将 CSS 和 JS 外部化时,为什么要使用它?
如果一个大文件是答案,那么我们需要建立一个系统
– 使用以下范例进行开发:外部 CSS 和 JS、语义内容等。
– 以类似 Java applet 的方式部署:jar、war
或者
– 使用工具组合所有这些内容并部署一个大文件
但是,这样一来,我们开始偏离标记语言和解释语言。走向拥抱依赖关系的世界。
不,这不是 KISS 原则,宝贝。
[…]
MHTML 文件的内容被编码为 HTML 电子邮件消息,使用 MIME 类型 multipart/related。文件的第一部分通常是编码的 HTML;后续部分是通过其原始 URL 标识的其他资源,并以 base64 编码。这种格式有时称为 MHT,这是 Microsoft Word、Internet Explorer 或 Opera 在创建此类文件时默认给定的 .mht 后缀。MHTML 是一个提议的标准,在 1999 年作为 RFC 2557 以修订版形式发布。
[…]
MHT 格式于 1999 年随 Internet Explorer 5 引入。[1] 使用此格式保存网页,可以将网页及其资源保存为单个 MHTML 文件,称为“Web 存档”,其中所有图像和链接文件都将保存为单个实体。但是,它可能无法正确保存某些复杂的网页,尤其是在包含脚本的网页中。
所以又回到了在 Word 中创建网页!哈哈。
酷!使用 Python 可以按如下方式编码
好吧,通过样式表加载时,base64 图像确实显示在 IE7 中(至少对我来说是这样)。
没事了,我正在 IE8 中测试,加载了 IE7 引擎……
IE8 在 IE7 模式下 !== IE7 的另一个很好的例子。
确实,我不会依赖它,再也不了。IETest == IE7,所以它很好。
但是,对于 IE7,您可以使用 PHP 脚本传递 URI 数据并使其工作。在某种程度上有点糟糕,但总比没有解决方案好。
PHP 自动编码技术非常酷,也许有一天会用在某些东西上。
至于 IE,您可以在条件注释中为不同版本创建“仅 IE 的 div”,然后在 CSS 中可以引用这两个图像。
所以类似于
#IE6 .sel, #IE7 .sel { background: original img; }
.sel { background: encoded img; }
哦,并且密切关注特异性是个好主意,这样您的 IE 规则就不会被编码图像覆盖。
太棒了!
:)
关于任何类型的 Internet Explorer,对我来说无所谓。我相信人们应该停止尝试让事情在 IE 上工作。
只是您检查 w3c 上的浏览器统计数据。拜托,做个男子汉,学习并了解如何对客户说“不”。
现在 IE9 看起来非常棒,最终微软解决了更多与 Web 标准协作的问题。
最好的,
真的吗?
让我想起了这个广告
让我们首先看看 IE9 在最终版本中会是什么样子。不要抱太大希望。
此外,微软到底在尝试什么?
那些不够聪明,不去升级更好的非 IE 浏览器的用户,也不会升级到 IE9。
投资一个具有坚实基础且以其良好性能而闻名的浏览器。例如 Safari 或 Chrome 中的 WebKit 引擎。
就这样……微软,结束了;回去工作吧。
我只是在这里大声思考,但是如果用这些做一些 if() 语句会不会很酷?例如,如果大部分图像为蓝色,则此页面的背景也应为蓝色,等等。可能不切实际,但如果有某种解释器,我可以看到一些非常有趣的功能。
我喜欢你的想法,即使它与手头主题完全无关 :)
使用 canvas 和 getImageData() 函数应该可以实现类似的功能。您可以使用它来确定图像的平均颜色,然后将背景设置为该颜色。例如,您甚至可以平均图像库中每个图片的颜色,然后以编程方式确定最适合它的配色方案。
它在 IE 中不起作用,但如果他们使用 canvas,它可能会在 IE9 中起作用。
就我个人而言,我不喜欢它。
#1:它很丑。我知道这不是什么充分的理由,而且可能很愚蠢,但我认为它很丑,并且不想那样弄脏我的代码。
#2:您正在将内容直接放入 CSS 文件中。当然,这与指定文件没什么区别(我猜这也是将内容放入 css 中,而且我看不到任何解决方法),但这仍然困扰着我。同样,这可能是一个愚蠢的理由,但对我来说感觉不对。
#3:我们都希望我们的网站尽可能快。我克服了很多障碍来提高网站的速度。但也有可能做得过头了。这是一个很好的技术,但我一直认为它有点过头了。
我想知道这是否对开发自定义 Facebook 页面有帮助。您必须使用他们自己的“FBML”编辑器,其作用类似于 HTML。
我想这对手机(它们没有快速连接)和电子邮件(它们不允许自动显示外部图像)很有用
但对于普通网站来说,这完全是矫枉过正
也许它也可以用来保护您的图像……这样它们就无法被复制。
好的,显然它们可以被复制,但它们不能引用您的网站,因此您的网站不会受到带宽问题的困扰。
这里的主要思想是图像会自动与 CSS/HTML 文件一起缓存,并且不需要其他 HTTP 请求。
非常有趣的技术,但我非常确定对于普通网站来说,这有点过头了。如今,普通大众的互联网连接已经足够先进,可以加载一次图像(并且稍后将其缓存)。
可能对移动/电子邮件网站有用,因为外部图像可能会导致问题。
不过不要忘记,如果不将图像链接到您的主机,您可能会丢失宝贵的统计信息。
很高兴能展示新技术,但语义呢?难道不应该 img = image 而不是哈希吗?
我不是硬核语义专家,并且经常尝试为自己找到最简单的方法,但使用真实图像的代码肯定比使用此哈希内容更易读。我们应该始终牢记,也许有一天我们的代码会被其他人修改。
因此,无论页面使用此技巧加载速度有多快,我仍然建议使用真实图像。
新技术?从 1999 年开始?
很酷,但伙计,这有点过头了。
我想我只会逗号。
该技术很酷,但从未流行起来(1999 年),因此基本上是一种过时的技术。最可能的原因是每个人都担心缓冲区溢出和互联网病毒。它仅受某些浏览器和电子邮件客户端支持。
如果 IE8 支持它,那就太好了,但 32K 除了几个 CSS 装饰之外,不会做太多事情。
几周前,当需要将 Windows ActiveX 控件的输出转换为可以发送给客户的电子邮件时,我偶然发现了数据 URL。
经过一些测试,我们决定简单地将数据 URL 转换为 MIME 扩展名(非常简单!)。
我同意。数据编码不是维护网站上图像的好方法。
因此,我编写了一个实用程序,它打开我的 css 文件,查找图像引用,然后对其进行 base64 编码。然后我输出一个 myprodversion.css。(我还进行了一些压缩)(我将来会将其集成到我的构建过程中,也许还会集成到 VS 插件中)。
缺点是我的 css 文件很大,但好消息是,我的 Web 服务器(在我看来,这现在应该是常态)将输出压缩到客户端浏览器,并且文本压缩效果非常好,而图像则没有。
因此,总的来说,结果是每个页面的 HTTP 请求更少(对性能非常有利)并且总体下载大小更小。
存在一些注意事项,它并不总是首选。但它确实在我的一个网站上运行良好,在该网站上性能优化非常重要。
Web 服务器执行的数据压缩不止一次出现在我的脑海中。
我应该说,最终,它应该位于协议栈中,而不是在 Web 服务器功能中。
这样我认为它会更有效,并且普遍认可。
不过,图像已经过压缩(除非您使用 *.bmp :))。
就我个人而言,我更愿意称之为 Base64 图像而不是数据 URI……
无论如何,我在创建 用于 Greasemonkey 的 markItUp! 脚本时使用了此技术。在 Greasemonkey 脚本中嵌入图像没有其他方法,并且我不想托管其他人在使用脚本时会调用的图像。使用 base 64 图像是完美的答案。
我还没有在网站上使用它——我一直想知道为什么它没有得到更广泛的使用,并且想知道是否存在一些缺点。
非常棒且简单。我一直在寻找这样的东西
感谢分享
我构建了一个小型实用程序来为收藏夹图像创建数据 URI。 http://bit.ly/a9VjTX
对于任何寻找简单方法将数据 URI 自动嵌入到 CSS 文件中的人来说,可以查看http://datauri.net。
它支持拖放、多个文件和自动 CSS 生成。
太棒了。这确实是一个很巧妙的技巧,并且介绍得很好。
谢谢。
这比使用雪碧图更好吗?
我使用http://base64image.org 将图片转换为 base64 格式。