为什么使用精灵表而不是单独的图片?

35
我注意到一些网站使用一个包含许多小图像的巨大图像,然后使用CSS的background-position来定义每个图像的坐标,而不是使用单独的图像。
以下是我对使用大精灵表的缺点:
  • 需要加载大图像才能显示一个小图像
  • 需要编写(或生成)带有每个图像类的长样式表
  • 使CSS混乱的类定义可能会影响性能
  • 如果更改一个图像(或添加另一个图像),可能会遇到缓存问题,这两个问题都与其关联的CSS有关
  • 需要一个经过适当样式处理的
    (display: inline-block; width: 32px; height: 32px; background-image: url('spritesheet.png');),这将向混合中添加另一个类。
  • 还有许多我现在无法记起来的问题。
事实上,唯一接近正面的事情是,当我将表格分成单独的图像时,生成的文件夹在磁盘上占用了3Mb的空间(由于每个文件少于100字节,并且我的分配大小为4k)。实际的文件本身的大小不到表和CSS的一半,因此即使有HTTP请求的开销,也仍可节省很多空间。
基本上,我的问题是:是否有人可以提供使用大表格而不是单独图像的任何优点?

2
从服务器检索一个“大”图像(它会被缓存)几乎总是比多次请求获取所有分离的图像要快。 - PeeHaa
5
你提到的缺点实际上并不是真正的缺点。 - thirtydot
1
这里是有关在网站缩略图中使用类似精灵的技术的优点: - Yisela
在元素在许多页面上重复出现的大型网站中,它只会提供最小的优势。否则就是浪费时间。 - Hal50000
8个回答

23

该目的是为了减少HTTP请求次数。此外,有时候经过压缩的雪碧图比原始图片的大小更小。

最近我有一个网站包含很多透明渐变(从白色到透明,灰色到透明)和一些黑白相间的透明图片。通过将它们全部放入雪碧图并将png中的颜色减少到8种,我可以使得雪碧图的文件大小比原始图片还要小(只有约0.5%的节省)。但是,由于HTTP请求次数从10个减少到1个,意味着网站的加载速度更快(如果从第一次连接到所有数据传输所需的时间测量)。

在这种情况下,确实发现了可衡量的提升。

不过,我同意如果你没有使用PNG压缩,很可能会把事情搞砸并得到一个比需要更大的雪碧图。

请注意,发布此文两年后——如果您正在使用SSL,则应查看SPDY(发布两年后的我的注释将提到HTTP 2.0而不是SPDY!)。SPDY取消了雪碧图的好处。


1
好的,但是如果这些图片被用于多个页面,但从未同时出现,那么拥有单独的图片逐渐导致它们全部被缓存会更好吗? - Niet the Dark Absol
当然,这取决于您所做的具体工作。一般来说,在页面上总会有一些可以合并的内容。我经常只将4个小图像合并,而将其余的留给实例。PNG是唯一值得使用此技术的格式,因为空白处几乎可以压缩到0。(相对于JPG或BMP) - Rich Bradshaw
我一定会检查 SPDY。 - alireza easazade

9

你提到的那些缺点实际上并不是缺点。

当你加载一张大图时,它只包含图片需要的一些属性(如颜色表、mime类型等),而不是将相同的信息分散在100个不同的文件中。这样可以从大局上减小文件大小。比如,如果使用渐进式jpg格式,则一个精灵图会使得图片只被扫描一次,而多个精灵图则会显著降低加载时间。

此外,这样只需要进行一次HTTP请求(或两次,具体取决于你有多少个精灵图),但如果处理得当,每个页面仅需一次HTTP请求。

如果在CSS中使用背景图片,则你已经定义好了CSS选择器,因此没有额外的工作量,只需要复制/粘贴URL即可。

我从未遇到过无法通过按下ctrl+F5解决的精灵图缓存问题。

这完全不需要一个带有适当样式的div。这不是用来替代<img>标签的方法,主要用于背景图片,例如按钮和图标集。

这种方法的优点远远大于缺点,事实证明已经被很多开发人员采用。如果这种方法很差,那么没有人会采用它,当它第一次被使用时,有人已经提出了这些问题。

如果有人还有更多的要补充,请不要害羞 :)


2
即使精灵表的大小为500kB,它也只会被下载一次,之后它将从浏览器缓存中获取。因此,请求的数量甚至更少:D - mingos

4

谷歌在这里描述了它。基本上,它应该可以减少页面加载时间。每次新建连接都会添加一些延迟。在某些情况下,它还可以减少数据传输大小,从而减少页面加载时间。对于很少更改或全部更改的图像(主题),这是合适的。然后浏览器可以使用缓存的图像,并且只需要检查一个文件以检查更改,而不是逐个检查每个图像。


不再推荐使用 Spriting。请改用 HTTP/2。 - Dan Dascalescu

2
精灵表是一团糟。毫无疑问,它们在设计技术方面是巨大的倒退,这也可能解释了为什么只有老派游戏开发人员喜欢使用精灵表。精灵表只有一个可取之处,就是加载速度较快。除此之外,它们就是垃圾。更不用说设置起来是一场噩梦。
在哪个世界上,需要包含500行代码才能运行一个简单的步行循环才是“可接受”的呢?希望一些聪明的人能想出一个像拖动自包含、支持alpha通道的视频格式(如flv)那样简单的解决方案,但这也要能在平板电脑上运行...
如果你觉得写一份关于精灵表有多好的大长串清单,我只能想象你的设计工作有多无聊。最重要的是,如果一个“工具”让你做本应容易的事情变得更难,那么它就不是一个好工具。扔掉它吧。

嗯,要不然我怎么可能最近才能在只有2.78MB的情况下制作出一部200帧、300x285像素的精彩动画呢?而且如果一个个下载这200张图片的话,不仅不一致(图片可能无法按照正确的顺序加载),而且还需要12MB的空间。雪碧图证明了它们的极大实用性。 - Niet the Dark Absol
是的,手工制作精灵表肯定是一场噩梦,但是有工具可以自动化每一个方面。 - Hanna

1
此外,它有助于保持您的CSS代码更加整洁。例如,我使用精灵图来制作按钮(这也意味着加载悬停状态图片时不会有额外的延迟)。
<button type="submit" class="vorige"><span>Vorige</span></button>

button  {display: block; width: 162px; height: 47px; background-position: 0 0;}
button:hover    {background-position: 0 94px; cursor: pointer;}
button:active   {background-position: 0 47px;}
button span {display: none}

.vorige     {background-image: url(../img/button/btn_vorige.png);}
.volgende   {background-image: url(../img/button/btn_volgende.png);}
.verstuur   {background-image: url(../img/button/btn_verstuur.png);}

由于精灵,我可以省略掉单独的悬停图像代码。
.vorige:hover   {background-image: url(../img/button/btn_vorige_active.png);}
.volgende:hover {background-image: url(../img/button/btn_volgende_active.png);}
.verstuur:hover {background-image: url(../img/button/btn_verstuur_active.png);}

一个常被忽视的好处。 - Hanna

1

是的 - 请求次数。

大多数浏览器在每个域名下只会并行下载约2个资源,因此如果您提供大量小图像,则用户必须等待大约一半的HTTP请求-响应周期。如果您使用精灵图,那么只需要一个请求和一个响应(尽管响应更大)。


1
现在不是这样,但是以前是这样的。现在大多数浏览器都有超过2个连接。 - Rich Bradshaw
对于HTTP/1.0,Chrome对每个域名强制限制为6个连接。对于HTTP/2(几乎所有浏览器都支持),则没有限制。 - Dan Dascalescu

1
如果您有很多图片,浏览器需要下载每一张。由于浏览器只能同时下载有限数量的文件,这将需要时间。单个图像只会占用一个下载槽,使页面渲染速度更快。
此外,如果在许多其他页面中使用,则大型精灵表已经被缓存。

1

这对于许多小图像特别有益,因为浏览器只需为所有图像执行一次http请求,而不是数百个请求。所以您的网站在客户端浏览器上加载速度更快。

关键是加载速度。仅一个http请求比几十个请求快得多。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接