CSS Sprites
CSS Sprites技术不新鲜,早在2005年 CSS Zengarden 的园主 Dave Shea就在ALA发表对该技术的详细阐述。原先只在CSS玩家之间作为一种制作方法流传,后来出来个14 Rules for Faster-Loading Web Sites, 技术人员之间竞相传阅,其中第一条规则Make Fewer HTTP Requests就提到CSS Sprites。于是这个小妖精就火了起来,甚至出现了在线生成工具,势不可挡也。近来国内很多blog都提到CSS Sprites,最著名的例子莫过于 http://www.google.co.kr/ 下方的那几个动画。最新发布的YUI中,也是使用到CSS Sprites,几乎都有的CSS装饰图都被一个40×2000的图包办。社交大站Facebook最近也使用了一个22×1150的图片承担了所有icon. 一时间,CSS Sprites无处不在。
原理
我们知道,自CSS革命以降,HTML倾向于语义化,在一般情况下不再在标记里写装饰性的内容而是把呈现的任务交给了CSS。GUI是缤纷多彩的,少不了各种漂亮的图来装点。新时代的生产方式是,在HTML布满各种各样的钩子(hook),然后交由CSS来处理。在需要用到图片的时候,现阶段是通过CSS属性background-image组合background-repeat, background-position等来实现(题外话:为何我提现阶段,因为未来浏览器若支持content则又新增另外的实现方法)。我们的主角是,你一定猜到了,就是background-position。通过调整background-position的数值,背景图片就能以不同的面貌出现在你眼前。其实图片整体面貌没有变,由于图片位置的改变,你看到只该看到的而已。就好比手表上的日期,你今天看到是21,明天看到是22,是因为它的position往上跳了一格。所以你也大概了解到,CSS Sprites一般只能使用到固定大小的盒子(box)里,这样才能够遮挡住不应该看到的部分。
我们使用YUI的sprite.png举个例子,假如我们有这么一段代码,max代表最大化,min代表最小化,我们需要给它们配上相应的漂亮图片(这样我们的网站才能够吸引人,才可以卖钱,才可以到佛罗里达晒太阳:D):
<div class="max">最大化</div>
<div class="min">最小化</div>
这两个class都使用同一个图片:
.min, .max {
width:16px;
height:16px;
background-image:url(http://developer.yahoo.com/yui/build/assets/skins/sam/sprite.png);
background-repeat: no-repeat; /*我们并不想让它平铺*/
text-indent:-999em; /*隐藏文本的一种方法*/
}
效果如下:
我们看到一团灰,没错,因为我们还没有指定background-position,默认为 0 0,可以看下sprite.png, 处于这个位置正是灰块。好了,我们要找到代表最大化的加号和代表最小化的减号的位置找出来。经过测量,最大化按钮位于Y轴的350px处,最小化按钮位于Y轴400px处。想一想我们如何才能让它们能够显示出来呢,明显,要向上提升sprite.png,得到代码如下:
.max {
background-position: 0 -350px;
}
.min {
background-position: 0 -400px;
}
耶,我们成功了:
(注意:为了举例的方便,本例子直接在HTML内置样式,切勿在实践中的非特殊情况使用这种方式)。
优点
我们从前面了解到,CSS Sprites为什么突然跑火,跟能够提升网站性能有关。显而易见,这是它的巨大优点之一。普通制作方式下的大量图片,现在合并成一个图片,大大减少了HTTP的连接数。HTTP连接数对网站的加载性能有重要影响。
缺点
至于可维护性,这是一般双刃剑。可能有人喜欢,有人不喜欢,因为每次的图片改动都得往这个图片删除或添加内容,显得稍微繁琐。而且算图片的位置(尤其是这种上千px的图)也是一件颇为不爽的事情。当然,在性能的口号下,这些都是可以克服的。
由于图片的位置需要固定为某个绝对数值,这就失去了诸如center之类的灵活性。
前面我们也提到了,必须限制盒子的大小才能使用CSS Sprites,否则可能会出现出现干扰图片的情况。这就是说,在一些需要非单向的平铺背景和需要网页缩放的情况下,CSS Sprites并不合适。YUI的解决方式是,加大图片之间的距离,这样可以保持有限度的缩放。
总结
性能压倒一切。CSS Sprites是值得推广的一种技术。尤其适宜用于FIR,比如固定大小的icon替换。为保持兼容性,图片中的各个部分保持一定的距离是一种不错的做法。
推荐阅读:
- CSS Sprites: Image Slicing’s Kiss of Death
- 14 Rules for Faster-Loading Web Sites
- High Performance Web Sites
更新:有网友问到IE6不支持png的问题。其实真相是,IE6不支持的是半透明(alpha transparency)的png,对于全透明的png, IE6并不存在问题。因此,在实践中,不涉及到半透明而需要透明背景的图片,其实都可以使用png, 这是很安全的。
October 8th, 2007 at 02:21
我们来起个中文名吧~hoho
直译:CSS精灵 显然不合适……
CSS图片组定位?……
October 8th, 2007 at 09:00
每次我这么做的时候都会用计算器算算…. 笨丫
October 8th, 2007 at 09:21
这招貌似在IE6下当多个ICON出现在同一页面会重复下载
很占客户端资源的说。。。
@Cloudream:
其实就是背景图片翻转定位的加大版嘛XD
October 8th, 2007 at 09:39
“为保持兼容性,图片中的各个部分保持一定的距离是一种不错的做法”。发现sprit.png背景是透明的。请问在ie6下怎么办?
October 8th, 2007 at 11:06
<!–[if lt IE 6]>–>
{
backgroud-image:none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,src=”我是透明的.png”)
}
IE下有滤镜呐呐呐~,如果只是单纯的透明,建议用gif在IE6上面来实现
October 8th, 2007 at 11:09
=。= 貌似条件选择的部分被屏蔽了,就是那啥if lt IE 6 | endif
October 8th, 2007 at 12:07
@炎妖儿
ie6下真有这个问题?关注中……
October 8th, 2007 at 13:06
@炎妖儿 滤镜和背景图的实现方法完全不同。滤镜怎样实现类似background-position的功能呢?
October 8th, 2007 at 13:17
@dexbol 忘了这衩啦~~~ 我的错,还是用gif去做透明吧,要用背景定位的话。
IE6下背景图既要定位又要alpha透明度,貌似俺没法实现
October 8th, 2007 at 14:37
ms网易邮箱也是这么干的
October 8th, 2007 at 16:30
看了一天google.kr的效果..好麻烦
水平还是不行
楼主能不能把那个效果给rip出来学习学习…
October 8th, 2007 at 16:31
[...] 如果你是一名Web Developer,而且还知道CSS Sprite这个词,请先去搜索一下(或者看看realazy的这篇文章),也许你正在使用这个技术,但只是不知道它的名字罢了。 [...]
October 9th, 2007 at 11:27
css 小鬼
October 9th, 2007 at 11:52
[...] 介绍文章: http://realazy.org/blog/2007/10/08/css-sprites/ http://hi.baidu.com/vivaid/blog/item/d9feb064842b43f3f736541e.html http://www.marchbox.com/blog/css-sprite-in-google-search/ http://blog.94smart.com/2006/07/21/821.html [...]
October 9th, 2007 at 12:00
@asing:
去蓝色理想搜索下,那个我记得以前有人发过
October 9th, 2007 at 16:31
[...] 另外一个就是CSS Sprites了,很久以前就见到过,不过操作比较复杂,所以一直没有用。今天,看到一个更详细的介绍,而且Yahoo和Facebook都在用这种方式,见这里和这里。我也决定紧跟一下潮流。 [...]
October 10th, 2007 at 12:14
好文,收藏至20ju.com
October 11th, 2007 at 08:45
so 老的技术…前年的东西了…
October 12th, 2007 at 22:27
[...] 原文:http://realazy.org/blog/2007/10/08/css-sprites/ [...]
October 15th, 2007 at 11:23
[...] CSS Sprites [...]
October 15th, 2007 at 11:38
虽然楼上有人说是老东西,但很多新人还是没有接触过。 学习下
October 16th, 2007 at 14:54
哥们我看着你的blog怎么昏昏欲睡啊。
太单调了?。。。。
October 19th, 2007 at 16:57
学习,收藏
October 20th, 2007 at 23:25
new skin,乍一看,以为进错站了呢。多了“skip to content”的链接。
October 22nd, 2007 at 12:48
又换回这个主题了,之前的不是挺好的嘛
October 25th, 2007 at 11:52
不错,其实很惭愧,我今天才知道这个学名叫做 CSS Sprites,虽然我已经用了好久了:)
吹毛求疵:
.min, max {
少了一个点,请编辑之。
October 29th, 2007 at 02:02
就一神经病!~YAHOO的程序员为了卖弄技术,发神经搞出这么一个华而不实的东西,楼主就跟着一起发神经也弄这么一个。。。
按每张图片增加300字节的连接HTTP的头信息,那么一百张图片就是30K,按512K ADSL 每秒下载速度70K计算,那么,楼主的方法可为我们节省不到0.5秒的时间(这是在网络状态良好的情况下,如果网络状态不好,节省的时间可延长至一秒),而确要浪费我们多少的人工成本~~~????
October 29th, 2007 at 14:01
用语错了
“IE6不支持的是半透明(alpha transparency)的png,对于全透明的png, IE6并不存在问题。”-
误
“IE6不支持的是半透明(alpha transparency)的png,对于不透明的png, IE6并不存在问题。”-
正
October 31st, 2007 at 23:45
VV 说得就不对。这种技术不是减少下载时间,而是可以减少浏览器发出的 HTTP 请求。一个图片就是一个请求,假设能够用一个图片代替原本的100个,对服务器的压力会小不少。
November 1st, 2007 at 09:59
你自己算算,算算HTTP连接请求数对服务器的压力增加多少?CPU增加多少,内存增加多少。。。尤其是现在HTTP服务器都会使用 Connection: Keep-Alive 以及连接池等底层技术的情况。。。
November 2nd, 2007 at 10:31
呵呵
对于一些小型服务器
硬件问题比较突出的
还是会有不少用的
@炎妖儿 如果在于IE6
真有问题的话
还得酝酿一下了
好硕大的提交按钮啊
November 6th, 2007 at 17:02
楼上的vv,在你不了解的情况下请不要随便骂街,这样不好。如楼主所说好处就是减少http请求数,而http请求数的时间和文件大小没有多大关系,理论上当然是 请求数越少,页面浏览速度越快,因为请求数少,服务器的响次也就少,可以有效的加快速度,减轻服务器载荷,至于你说的下载来说,理论上第一访问感觉是要慢一些,因为网速和文件大小原因,需要下载比较大的文件然后显示,但是实际上总体的速度是要提高的,而且再加上客户端缓存和本地缓存,速度会更快。
如果不相信你可以拿一些测试软件去测试。
November 13th, 2007 at 19:02
你把整个网页用 FlashPaper2 打印成 Flash,只要一个连接,网页就打开了。
November 13th, 2007 at 19:03
另:你们比较厉害,你们都是做雅虎的程序员,我不是。
能用硬件解决的问题,我绝不用人工来解决。
雅虎他们那是实在连硬件都解决不了了。。。
November 14th, 2007 at 22:01
[...] 我最早是在 realazy 看到 CSS Sprites 的介绍(如果你不知道什么是 CSS Sprites,那么一定要好好这篇文章),紧接着 Zhang-Zi 在自己的阅微堂上应用了这一技术;此时此地,我也把它实现了,(基本上)这里的全部背景图片(虽然也只有几张)都用一张图片包办了,blog 加载的速度显然比之前快了一些。 [...]
November 19th, 2007 at 22:26
减少requests.比较有用
维护成本有时候来说也还可以
继续向下加px..上面的删掉。哈哈
December 4th, 2007 at 20:53
[...] css图片拼合。减少下载的次数。网上搜索到一些资料CSS 图片拼合 (CSS sprites),div+css布局实例淘宝分析(二), CSS sprites 中文介绍。 [...]
December 25th, 2007 at 11:14
貌似是以前是做ui的技术
December 28th, 2007 at 17:36
[...] CSS Sprites Introduction http://realazy.org/blog/2007/10/08/css-sprites/ [...]
January 1st, 2008 at 16:12
[...] 去年(是啊,今天可是 2008 年了,各位写日期时别搞错了啊 - -)写过一篇关于 CSS Sprites 的文章,由于已经有大量的文章写它的原理,我只是敷衍两句罢了。 [...]
February 13th, 2008 at 00:24
[...] CSS Sprites 其实这一技术我们早就在使用了,只不过,现在知道了,她有个学名叫做 CSS Sprites (tags: css) [...]
March 9th, 2008 at 10:01
老技术了,最早用这个的时候是因为设置按钮link和hover的不同状态时如果使用两张图片hover时因为要临时下载,会出现延迟。
后来用一张图片对背景做定位,感觉挺方便,就经常这样用了。经常把一些比较固定的功能性的小图片可以综合放在一起,既是为了减轻服务器压力,也为了防止有个别图片下载不下来。
只不过现在刚知道他叫CSS Sprites。
May 26th, 2008 at 09:10
刚知道这个叫这个名惭愧……之前看淘宝站时看到过,当时也没有细想~
现在想想,这倒真是不错(就是好麻烦)
June 3rd, 2008 at 12:37
css sprite在EXT/YUI里大放异彩,这也是比其他JS库领先的地方
June 21st, 2008 at 00:05
做这种东西不妨多想一步,平时用零散图片来开发,发布时用程序来合并图片,并生成最后的网页。兼顾开发和运行的效率。
July 1st, 2008 at 11:45
27楼这样说就不对了。 如果每天有1000万人访问你的服务器,你想这一个小技术给你服务器减少了多少压力。 如果你网站只是每天几十IP,那你全站用图片都可以。 就不用学什么CSS了。