使用数据 URI 优化层叠样式表 CSS

Data URI 是由 RFC 2397 定义的一种把小文件直接嵌入文档的方案,是一种非常有效的将图片嵌入 HTML 的方法。平常我们在 HTML 中嵌入图片都是通过链接到服务器上的图片资源来实现,而这种方法是将图片使用 base64 将图片本身编码成一串字符,字符串前面使用 mime 类型来标识该字符串所代表的资源类型。合理地使用 Data URI 可以加速网页加载、提高性能,还能降低服务器的资源消耗。

1. Data URI 简介

HTML 中的图片一般都是用类似下面的标签来链接使用:

<img src="images/myimage.png">

这里,src 属性指定图片资源所在位置。浏览器加载页面的时候会向服务器发送请求来获取该图片资源。对于一般的图片引用,我们当然选择这种方法,而且还可以使用 Lazy Load 方式来按需请求和加载相应图片。但是某些页面图标,本身体积很小,浏览器发送请求、获准、下载的时间和资源开销就显得很不划算。对这种图片就可以通过下面的方式将图片嵌入到 HTML(实际往往是 CSS)里面,这样浏览器获取 HTML 或者 CSS 之后就可以直接使用而不需要再另外请求和下载该资源了:

<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAAAolBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGBgYAAAAAAAAAAAAFBQUFBQUEBAQEBAQEBAQICAQEBAQEBwQHBwcHBwcHBwcHBwMHCgMGBgYKCgoGBgYJCQYJCQkJCQkICwgICAgICwgICwgICwgICwgICwgLDQtGnG0lAAAANnRSTlMAAQIDBAUGDQ4PEBEUFRobHB4gIiMkJigsLjAyMzk6PEFCRUZISUtMUFBRVFdZW1xcXV5fYGEIq40aAAAAkElEQVQYGZ3B2RZCUAAF0CNEAyql0iiNaDCc//+1ZK2L7kMP7Q38ZPQ1fFMWCVkEJlqUA5k/yKeFhs/U62BwZqJDUF90UdJiziFYvKOy5B6CwysqM4YQesy6+Nhwi1rEHUrDjDZqdsGT66xThmioCStHHY0VGV1uwQQtZs7MgCQkfUgcMlYhmZIjyBRvjD+9Af7aD071jQI/AAAAAElFTkSuQmCC">

可以看到,前面的 src 的值是一串指向具体图片的路径,而这里是一个代表图片内容的字符串。经过浏览器渲染之后,这两种方式的效果是一样的。

2. 浏览器支持情况

既然需要浏览器的支持才能完成这个任务,我们就需要关心一下都有哪些浏览器支持这种方式。幸运的是,目前的绝大多数浏览器都支持:

  • Firefox 以及所有使用 Mozilla Foundation 的 Gecko 渲染引擎的浏览器
  • Safari、Chrome 以及其它基于 WebKit 的浏览器
  • Opera
  • Konqueror
  • Internet Explorer 8 及以上版本 IE 浏览器(可恶的 IE6 现在还有很大市占率,恐怕不是好消息)

3. 为什么要使用 Data URI?

相对于传统的资源引用方式,Data URI 比较适合以下这些使用情景:

  • 图片的体积很小,浏览器发送请求、获准、下载它的时间和资源开销很不划算;
  • 图片是由服务器上的程序根据访问情况不同动态生成的;
  • 某些情况下获取外部资源很难或者受限制。

Data URI 的优势

其优势表现在:

  • Data URI 节省 HTTP 请求。Data URI 可以减少浏览器需要发送的 HTTP 请求数量。因为图片数据在链接地址 URL 里面,不需要从别的位置下载,也就不需要额外发送 HTTP 请求了。减小浏览器需要发送的 HTTP 请求数是优化网页加载时间的一项重要内容,因而 Data URI 可以提高网站性能。
  • 快速传输小文件。对于传输小文件来说,Data URI 可以有更高的下载速度。传输数据需要发起 TCP 连接,而这个比较慢。每个外部资源都会发起一个新的 TCP 连接到服务器。因而传输速度会因为发起 TCP 连接本身的时间消耗而降低。甚至有可能发起 TCP 连接的时间比下载时间都长得多。
  • 某些情况下会有更少的带宽占用。一张 600 字节的图片,转成 Data URI 后是 800 字节。当发送 HTTP 请求的开销大于 200 字节的时候,Data URI 使用的带宽就更小。目前的带宽水平,这个貌似可以忽略不计了。
  • 更快的 HTTPS 连接。因为 SSL 加密的原因,HTTPS 请求比普通的 HTTP 请求需要花费更多的时间。如果你的网站使用 HTTPS 连接来提供内容的话,Data URI 的益处是显而易见的。

Data URI 的缺点

Data URI 也并不总是有好处。以下一些不利因素需要特别注意:

  • 重复利用。在同一个文档(或者说是 HTML 网页页面)中如果要重复利用同一张图片,则使用 Data URI 的话就必须每次都将其字符串完整的引用一次,所以当一幅图片在同一文档中多次使用的时候,就需要占用多倍于此图片体积的带宽。
  • 缓存Data URI 不能独立于包含它的文档来缓存。所以只要包含它的文档被下载,则它就随之重新下载。也就是说,如果浏览器要重新加载一个包含了 Data URI 的 HTML 文档,就必须重新下载整个包含了 Data URI 资源的 HTML 文档。
  • 资源改变时需要重新编码。每当图片发生变化时,其整个 Data URI 编码都必须重新生成。
  • 早期版本的 Internet Explorer 浏览器不支持。低于 Internet Explorer 8 版本的 IE 浏览器都不支持 Data URI。
  • Base64 编码会增加数据量。Base64 编码的 Data URI 比原来的图片文件数据量大了大约 33%。但是,如果服务器上使用了数据压缩, 则体积只会增加大约 0~10%。
  • 尺寸限制。根据 Data URI 规范,浏览器只需要支持最大 1024 字节(bytes)的 Data URI。虽然大多数浏览器都能接受更大的 URI。Opera 限制在大约 4100 个字符,Firefox (Mozilla) 最大支持 100 KB、Internet Explorer 大约 32 KB、WebKit (Safari 和 Chrome) 似乎没有限制。但是一般情况下,当图片比较大的时候,使用 Data URI 就没有什么优势了,它们一般用于小图片(大约 1-4KB)

因此,Data URI 最适合于用在 CSS 样式表文件中,针对那些在一个页面中只出现一到两次,体积又很小网站图标或背景图案。

4. 在 CSS 中使用 Data URI

如果不能带来性能上的提升,就没有理由费事地将图片转换成 Data URI。

在浏览器中,缓存是一个非常重要的功能。要让 Data URI 在浏览器中能够享受到缓存带来的好处,只能通过层叠样式表(CSS, Cascading Style Sheets)了。CSS 中的 url 操作码让我们可以为元素指定背景图片 —— 浏览器并不关心是什么样的 URL 地址,它只要能得到相应的数据就可以了。所以我们可以将 CSS 中那些背景、图标等转换成 Data URI。那么,同样体积的图片或图标只需要其 Data URI 随着 CSS 下载到浏览器就可以缓存并重复利用了。但是如前所述,如果同一个图标在 CSS 中反复多次出现,那就需要权衡一下了:每出现一次,CSS 的体积就大了一点,我们需要权衡这样做是否值得,因为如果只给个链接,这个图片也只需要下载一次(但是需要在下载 CSS 之后另外发起一次 TCP 请求来下载该图片)然后被缓存在浏览器中。

很多页面背景使用了平铺的图案,图片本身也许只有几个像素大小,体积不过几个kb甚至不到1k。例如一个 3×3 像素的图片,保存成 GIF 或者 PNG 格式。如果使用 Data URI 就可以写成,

.box
{
	width: 100px;
	height: 100px;
	background-image: url("data:image/gif;base64,R0lGODlhAwADAIAAAP///8zMzCH5BAAAAAAALAAAAAADAAMAAAIEBHIJBQA7");
	border: 1px solid gray;
	padding: 10px;
}

剩下的就跟平常的 CSS 用法一样了。

如果使用恰达,Data URI 可以大大的提高网站的性能,加快页面渲染速度。

5. 从图片创建 Data URI

剩下的问题就是,如果将一幅图片转成 Data URI,也就是如何进行 base64 编码的问题了。

dataurl.net 提供了两个工具,一个是将提交的图片转换成 Data URI,另一个是,你将网站的 CSS 提交给它,它自动对 CSS 文件进行扫描和优化,然后将优化后的 CSS 提供给你下载。dataurl.net 上的后台代码可以在 GitHub 上找到,使用 perl 编写。

下图是使用 datauri.net 优化水景一页讨论区整个儿 CSS 文件的截图,图中右下角红框所在位置提供了优化后的 CSS:

使用 datauri.net 优化水景一页讨论区整个儿 CSS 文件的截图

使用 datauri.net 优化水景一页讨论区整个儿 CSS 文件的截图

我还是比较喜欢自己动手,只让它转换图片成 Data URI,然后我自己替换到 CSS 里。因为有些图片我希望继续保持原来的下载方式。

本文内容大部分编译自 http://sveinbjorn.org/dataurls_cssDataURL.net©

本文发表于水景一页。永久链接:<http://cnzhx.net/blog/data-uri-css/>。转载请保留此信息及相应链接。

2 条关于 “使用数据 URI 优化层叠样式表 CSS” 的评论

  1. 我擦…
    看我开头的love.sas.sky.css
    几k的图片居然这么长一串…
    文字大小都差不多有图片大了

    • Data URI 一般都比对应的图片本身的体积大,用它的好处就是可以少一次 HTTP 请求嘛。我只在页头上那个搜索框里的放大镜上用了这个。

时间过去太久,评论已关闭。
如果您有话要说,请到讨论区留言并给出此文章链接。
谢谢您的理解 :-)