文章目录
译者:AlphaImageLoader是一个让IE6正常显示PNG32时要用到的一个滤镜,但它在使用中也会产生一系列的问题,本文对使用AlphaImageLoader及替代方案都做了很详细的分析和总结。关于图片优化YUIblog有五章内容,其它内容大家貌似都懂,有兴趣的同学译吧。关于PNG32在Photoshop中导出的叫做PNG-24,但在Fireworks导出PNG会有三种格式,PNG8、PNG24、PNG32,它导出的PNG24是没有透明度的,为了防止大家搞错,所以我译做PNG32。
原文地址:http://yuiblog.com/blog/2008/12/08/imageopt-5
译文地址:https://s5s5.me/?p=2286
作者Stoyan Stefanov在雅虎的性能优化团队工作,领导开发YSlow性能工具。同时他还是一个开源贡献者、演讲者和技术作家,他的最新著作是《Object-Oriented JavaScript》。
本文是图片优化的第五章。点击以下链接查看其他章节:
本章图片优化主要介绍IE浏览器私有CSS滤镜:AlphaImageLoader,开发人员经常使用它来解决在IE下显示PNG32图片的透明度问题。但使用AlphaImageLoader会使网页性能降低,从而伤害用户体验。所以我认为应改尽可能避免使用AlphaImageLoader。
快速复习
我们在图片优化 第二章:选择正确的文件格式一文中提到,PNG格式有几种不同类型,大致可以分为:
- Indexed (palette),也被称为PNG8有多达256种颜色。
- Truecolor PNG,也被称为PNG32或PNG24,所有颜色都不会丢失。
这两种格式都支持 Alpha(变量)透明,但在IE6下PNG8显示为如同GIF图片一样的无变量的透明(例如,来源),PNG32则在原本显示透明背景的地方显示成了灰色(如下图所示)。
AlphaImageLoader修复
IE6(及更老版本的IE)提供了一个针对PNG图片显示的解决方案,通过其私有CSS滤镜。以下代码可使PNG图片在浏览器中正常显示:
#some-element { background: url(image.png); _background: none; _filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='image.png', sizingMethod='crop'); }
你会发现,下划线的CSS Hack被用来针对IE6及更老的版本,它的作用是:
- 不显示背景图片
- 使用微软的AlphaImageLoader滤镜加载背景的PNG图片
因为IE7不使用CSS淲镜也能支持PNG图片的Alpha透明。(但IE8中又不一样,它实际上完全改变了CSS滤镜的语法 。)
该滤镜的有趣之处在于,它并没有改变图片,相反,它在改变使用该滤镜的HTML元素。而更有趣的是,它对所有使用它的元素都只在一个UI处理线程中处理。这个过程中每个使用该滤镜的元素都要消耗系统资源,当你使用滤镜越多情况就会越糟糕,即使你所有元素其实是用同一张图片。
现在的问题是:这将如何影响该网页的表现?
假死!副作用#1
这里有一个简单的实验:创建一个页面,有一个CSS滤镜,然后模拟(和增大)网络中的延迟,延迟10秒加载淲镜中使用的图片。结果呢?在这10秒中什么也没显示(空白页),并且浏览器也会假死,这意味着你不能与浏览器进行交互:单击图标、菜单、键入网址…通通不行,甚至更不能关闭它。
在这个例子中,我没有用下划线,所以你可以看到在IE7下也一样会假死,即使在IE8的“兼容模式”下。
虽然效果演示的是夸张了的,但网络延迟也生活中的事实,这可能是最糟糕的用户体验,这意味着:有人来到你的网页,然后你让他的浏览器假死。
需要注意的是,它不阻塞并行下载。浏览器其实在后台还在下载其他网页文件,但没有进行渲染。你可以这样认为:IE不会渲染任何元素,直到所有的CSS下载结束(更多信息)。就是因为CSS中有一个图片的依赖于滤镜加载,所以CSS被认为没下载结束,导致IE不去渲染页面,直到依赖滤镜的图片被加载到。
如果你在网页中使用了多个AlphaImageLoader滤镜会怎么样呢?他们会一个接一个的处理。比如你有5个图片,每2秒延迟在服务器上,哪么浏览器就会有10秒的假死状态。
时间与内存 – 副作用#2和#3
另一个使用AlphaImageLoader的副作用是它要使用更多的内存。这个问题,我们一般会认为访问者的电脑内存是足够的,但对于更早的电脑(可能还在运行IE6或更低)则可能并非如此。
所以,它的性能问题则是我们最感兴趣的,衡量性能需要测试它在浏览器中表现。所以,让我们做一个使用时间及内存的测试。
首先,让我们做一个参考页:它使用了100个<DIV>且它们具有相同的背景图片(不使用滤镜)。然后我们再做一个100个<DIV>背景相同但使用滤镜来实现的页面。使用100个滤镜来呈现背景的页面可能在一般的页面中不常见,但这样放大将帮助我们更好的测试。它将显示出每个页的“价格”。(译者:作者在这里创造了一个“价格”,是为了说明每个元素或每个页面中要消耗多少系统资源。)
时间从页面的onload事件后开始计时,图片也已经缓存,这样用以消除需要加载网页和图片的影响。内存消耗使用ProcessExplorer来帮助我们测量。
这里统计了一台双核2GHz CPU、500MB内存电脑的IE6中的10次结果。在一个不这么强大的电脑中,加载时间可能会更糟糕。
测试页 | 时间(秒) | 内存(MB) |
---|---|---|
测试#1 – 无滤镜 | 0.031 | 0.6 |
测试#2 – 有滤镜 | 0.844 | 46.8 |
正如你可以看到,使用AlphaImageLoader的结果是相当的糟糕——测试页加载慢了27倍而且使用了78倍的内存。当然这些结果有很高的随机性——这只是一个图片且只在一台电脑上的测试(相对强大且未尽其用)。由于不同的图片,应用于不同的元素的数目及不同的电脑,结果可能有很大的不同,特别是当只有较少的内存和CPU或者把网络延迟(副作用#1)也加入统计。但这个例子说明了重要的概念:
- AlphaImageLoader是缓慢的,它需要更多的内存
- 它对的每个使用它元素的起作用,而不是每张图片
如果你有一张雪碧图并且你使用的滤镜于不同的元素(使用Alpha透明的雪碧图是非常棘手的,但也不是完全不能用),那么每个使用雪碧图的元素都会消耗更多的系统资源。
雅虎搜索案例研究
使用上面AlphaImageLoader实验测试中的“价格”理念,你可能想象或计算出要为每个滤镜使用多少的系统资源。但一个百万级在不同的浏览器、电脑、带宽和世界各地的测试能更好的说明这个问题。
雅虎的搜索结果页曾经使用PNG32雪碧图且使用AlphaImageLoader来实现透明度(旧版本的雪碧图仍然存在,如果你很好奇)。如果更换成PNG32为颜色有损的PNG8(以前讨论过)能降低50-100ms的页面加载时间为IE5-6用户。100ms可能并不起眼,但相对于使用滤镜的页面,它至少节省了10%的时间。此外,根据亚马逊研究,100ms的速度意味着1%的销售会减少(即使他们是内容型网页)。增加1%的收入而只需要更换一个图片看起来是笔好买卖。
所以,现在怎么做?
最好的事情是避免AlphaImageLoader像雅虎搜索一样,花时间去创造PNG8让它在IE6及其它浏览器中都有最好的表现。那么如何创建一个优美的PNG8呢?首先创建一个GIF图片,只有一个完全透明或完全不透明的像素。然后确保它看起来可以接受的(如同它在IE6的表现),继续加强与半透明有关的像素比如圆角或任何受益于透明度的图像。遗憾的是,据我所知,Fireworks是目前唯一使PNG8拥有Alpha透明度的图像处理软件。你也可以尝试其它工具,如命令行工具 pngnq和pngquant,但因为自动PNG32到PNG8的转换不是总令人满意,你可能需要手动选择完全不透明的像素。
可能有这样的情况:当你将无法用PNG8达到效果而一定需要使用AlphaImageLoader——例如当大部分或全部图像是半透明(比如视频缩略图上的“PLAY”图标)。Dave Artz在美国在线有一些 其他案件显示PNG8并不够完美。在这些情况下(当然,也在你尽量说服设计师重新考虑使用透明度未果情况下),请确保你使用下划线HACK(_filter),使之不影响IE7的用户。
有时,有人用为IE6使用GIF而为其它浏览器使用PNG32,但是这样完全没有必要,一个PNG8就能在兼容两种不同的显示和alpha透明。
使用PNG8的更多好处:
- PNG8通常比PNG32小
- 在所有浏览器下只使用一个图像
- CSS比较清爽,不用特别使用HACK或标签
- 背景能够平铺
VML的透明效果
使用VML是另一种在IE中使PNG32透明的方法,它解决了几个问题:Alpha透明,性能和背景重复。可惜的是,它使用了非标准标签(也可用JavaScript来生成,如果你希望你的初始标签清爽)和私有CSS。这里有一个如何实现它的例子。
例如,你有一个 的DIV,你需要用VML的 :rect (或 :shape) 和 :fill 标签来把包含它,如:
<v:rect>
<v:fill type=”tile” src=”alphatest.png”>
<div> </div>
</v:fill>
</v:rect>
某些标签之前,你还需要声明VML命名空间:
<xml:namespace ns=”urn:schemas-microsoft-com:vml” prefix=”v” />
而在你的样式表,你需要:
v\:rect {
behavior:url(#default#VML);
width: 100px;
height: 100px;
display: block;
}
v\:fill {
behavior:url(#default#VML);
}
测试页显示100个VML rect元素装载用时0.094秒(几乎是使用滤镜速度的10倍)和使用4Mb内存(是使用滤镜的1/10)。
正如你可见,这种解决方案增加了更多私有标签和CSS,但它仍然是一个相对于AlphaImageLoader的“价格”高的解决方案,。
(感谢Drew Diller的这篇文章 及 HTML Remix,从中无意中发现了这个方案的另一作用,解决工作中的另一难题——通过使用VML实现圆角,如:snook.ca)
P.S…其他过滤器怎么样?
AlphaImageLoader不是唯一的滤镜。另一种经常使用的是opacity滤镜。
例如,对于50%不透明度开发人员使用以下属性:
- opacity: 0.5(标准)
- -moz-opacity: 0.5 (Mozilla的早期版本,在FF 0.9之前)
- IE浏览器:filter: alpha(opacity=50)
在IE6做一个快速测试,该滤镜消耗低于AlphaImageLoader,但它仍然使页面慢,并且消耗了相同数量的内存。该测试使用颜色做背景,没有使用图片做背景,但使用图片的结果也大致相同。
测试页 | 时间(秒) | 内存(MB) |
---|---|---|
测试#3 – 100 Divs,不使用 opacity | 0.016 | 0.2 |
测试#4 – 100 Divs,使用 opacity | 0.093 | 46.7 |
这个东西好。 👿
IE6的PNG真是餐具,快点灭亡吧IE6。
十分详细啊,覆盖面很广. 😛
赞~
可以换个角度考虑,IE6下大量使用滤镜,让那些使用IE6的受不了后主动升级浏览器,哈哈~~邪恶~~ 👿
太太太太详细了!~
好东西!
好文章,翻译的很好,希望博主有时间能把另外的几篇也翻译一下。(好像有点过分,呵呵)
我想去掉滤镜效果,该怎么替换呢?