IE6下png背景不透明问题的综合拓展

这篇文章发布于 2009年08月22日,星期六,00:18,归类于 Web综合。 阅读 304193 次, 今日 5 次 33 条评论

 


IE6以下浏览器这里不考虑。

前言:IE6不支持png背景透明或半透明。其解决方法有IE滤镜,纯粹的JavaScript,以及jQuery等,正所谓事非经过不知难,让png图片在IE6下背景透明显示只是第一步,如果对这些png图片做进一步的操作,往往会出现各类莫名的问题。而本篇文章讲详尽阐述png背景透明会出现哪些问题,一些自己的经验之谈和一些相关的拓展。内容较多,有一定的深度和广度,希望对大家有帮助。

目录
一、可解决的方法
1. css滤镜
2. 老JavaScript方法
3. jQuery实现
4. flash实现

二、产生的问题
1. 响应单击事件
2. 图片大小控制
3. 背景图片的定位

三、相应的解决方法
1. 响应单击事件
2. 图片大小控制
3. 背景图片的定位

四、相关延伸的问题
1. png8与png24的半透明显示
2. IE7的半透明滤镜与png背景透明

五、小结

一、可解决的方法

1. IE css 滤镜
IE css滤镜中有一个使png背景透明的滤镜,JavaScript方法也是应用的这个滤镜实现png背景透明的。
写法:filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’../image/png_test.png’);
用法示例:
.png{background:url(../image/png_test.png);}
* html .png {background:none; filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src=’../image/png_test.png’);}
非IE6浏览器使用正常的background定位,IE6去除背景图片,应用png透明滤镜。
如果您的浏览器或内核为IE6,强烈建议点击这里进入demo实例页面

2.传统的JavaScript
使用传统的JavaScript方法,页面只要链接一个小巧的JavaScript文件就可以。例如,您可以在页面上添加如下代码:

<script src=”http://www.zhangxinxu.com/study/js/png.js” type=”text/javascript”></script>

这个JavaScript文件是我之前一直使用的使png背景透明的JavaScript文件,它可以让页面上所有的含有透明背景的png图片透明显示,支持background-image的png图片透明,但是不支持background-position定位;另外也不支持type类型为image的input框的png图片透明。

如果您是IE6或内核是IE6的浏览器,强烈建议点击这里查看demo实例页面
在这个页面,您可以清晰的看出此JavaScript的应用范围以及局限性。

3.jQuery png背景透明插件
相对于前面的方法,jQuery的IE6下png透明插件相对要强大些。
此插件js下载:jquery.pngFix.pack.js
使用的时候还要链接jQuery文件。
此js的强大之处在于不仅支持IE6下img标签的png背景透明,background-image的背景透明,还支持image类型的input的png背景透明那个,而且实现的精确控制,即您可以让页面上任意一张png图片背景透明而其他不受影响。

不管您是什么浏览器,强烈建议您点击这里进入精彩的demo实例页面吧。
您可以在这个页面上感受到此png 背景透明插件的强大。

4.使用flash装载png图片
使用flash装载png的原理是:flash对png的透明背景支持非常好,只要用户安装了flash插件,通过flash显示的png图片的背景必定是透明的。
实现的方法有两类,一种适合对flash不太熟的,就是直接将图片嵌入到flash中,方法如下:打开flash软件->设置舞台大小->将png图片拖到舞台(或导入到舞台)->导出flash->将swf插入在页面中->完毕;但是这种方法维护不讨方便,如果要更换图片,还要动flash源文件。另外一种就是与页面交互,从页面获取图片路径,最简单的方法之一就是通过FlashVars传参,再在flash中写上极短代码就可以了。

如果您感兴趣,建议您狠狠地点击这里进入demo实例页面参观参观。
页面上显示了flash获取页面参数的ActionScript代码,ActionScript 3.0代码,需要至少flash cs3版本的flash软件,直接写在第一帧上就可以了,另外设置舞台大小与图片一样大。

二、产生的问题

1.无法响应单击事件
这个问题在各个解决方法中都是存在的(即使是flash封装png的方法,其本身也不能响应click事件,只能背景透明情况下响应onmousedown事件),不是指本身无法响应单击事件,而是其内部的标签无法响应。举个简单的例子吧,一个div标签,里面有个a标签,a标签有个链接指向或有个js响应事件,而这个div标签有个png透明背景的图片,且在IE6下经过透明处理,那么这个a标签就是聋子的耳朵——摆设,只能看不能用。多说不宜,眼见为实,如果您的浏览器是IE6或内核为IE6请狠狠地点击这里,去感受下我所说的单击不响应是怎么个不响应法吧。如果您现在使用的是Firefox,chrome或是opera,Safari,但是您有该死的IE6浏览器,建议您委曲求全,也进来看看。

2.图片大小控制受到限制
这个问题在css png透明滤镜和老式的JavaScript方法中会遇到。问题简述如下:咳咳,一个img标签的src路径指向的是个含透明背景或半透明的png图片(例如:<img src=”xx.png” />),并且在IE6下,此图片受css滤镜或老式的JavaScript png透明处理,那么对该图片进行的任何大小限制拉伸都是瞎子点灯——白费蜡。再具体点说吧,假设我们这里的xx.png原始大小128像素*128像素,您使用css,img{width:256px; height:256px;}或是直接<img src=”xx.png” alt=”” width=”256″ height=”256″ />再或者是用上style<img style=”width: 256px; height: 256px;” src=”xx.png” alt=”” />要将他拉伸到256像素*256像素,您会发现有条比蜀道更难走的路——这张图片还是以其原始的大小显示,只是占据的空间变了。

上图为demo实例页面的小小截图,如果您是IE6浏览器,您可以狠狠地点击这里去看个清楚看个究竟。

3.无法对背景图片进行background-position定位
有个名词叫做css sprite。貌似是说很多背景图片集中到一张大图上,通过background-position定位,用到哪张图片就显示那部分区域,这好处大大的多,使用流行的很啊,优化大小,减小服务器压力,好处很多,里面颇有学问,但不是本文重点,不偏题。这个css sprite背景定位技巧在web2.0中可谓呼风唤雨,如鱼得水,但是遇到IE6浏览器,有时候他也只能哭了。如果背景图片是个含有透明背景的png图片,同时应用了IE6下背景透明显示处理的话,则该背景图片对background-position完全免疫。随便上面那个demo实例页面,保存下来,给这些background-image为png的图片再添加个background-position试试(比如background-position:-100px -100px;)您会发现不管用。如果您不想麻烦,直接狠狠地点击这里去看看吧。ps:要是IE6浏览器,不然没有效果的哦!

三、问题响应的解决方法

1.无法响应单击事件
要解决内部标签无法响应单击事件的问题,关键要把内部标签拿到外部,使用其他方法进行覆盖定位;或是不拿出来,使用另外的一个透明层或是透明图片进行定位与覆盖。最关键了一个词:覆盖;最难点:定位。说到覆盖性质的定位,无非两类,一是相对或绝对定位,二是margin负值定位。由于IE6下,父标签是position:relative;或是position:absolute属性时,里面的绝对定位层有时候会莫名消失,所以自己偏好于margin负值定位以及position:relative的负值定位。在此问题的demo实例页面最后一栏给了一个解决方法,margin负值定位解决的。方法很多,也很自由,就是覆盖,定位。您有兴趣可以试试点击这里去看看如何进行定位,如果解决此单击不响应问题的。

2.图片大小控制受到限制
这个问题的解决,说出来您不要笑我,就是去使用强大的jQuery png透明插件吧。这个插件不仅可以让指定的png透明,还支持image类型的input的png图片背景透明,更加重要的是其支持png图片的任意拉伸。
如果您是IE6浏览器,建议您狠狠地点击这里去看看图片美妙的拉伸控制,如果您目前使用的不是IE6浏览器,但是有,也建议您去看看。

3.无法对背景图片进行background-position定位
无法对背景图片进行background-position定位,那就拿到页面上进行定位就好了。使用img标签,src链接此背景大图,或是用span标签,其高宽就是整个大背景图的高宽,背景图片就是大背景图,在页面上对img或span这类标签进行定位,即可实现您想通过background-position实现的效果。
两大方法,margin定位与position定位。

这里需要分情况叙述。
首先,如果您直接使用的是css 滤镜或是传统的png透明JavaScript的话,这里的定位就是纯粹的margin定位或是absolute定位。这里概念说得比较含糊,实例说明吧。例如,我们将使用下面这张png按钮图片作为实例素材进行说明。

a.如果您使用的是css png透明滤镜,则需要将此png图片写在背景里,否则滤镜不起作用。写法如下:<img src=”http://www.zhangxinxu.com/study/image/pixel.gif” width=”640″ height=”80″ style=”background-image:url(http://image.zhangxinxu.com/image/blog/200908/png_btn.png);” />(说明:这里的background-image要写在css里面,这里是为了方便说明才用style表示的)然后您所要做的就是对这个img标签进行margin定位或absolute定位。

例如,我这样写,<div style=”width:160px; height:40px; overflow:hidden;”><img src=”http://www.zhangxinxu.com/study/image/pixel.gif” width=”640″ height=”80″ style=”background-image:url(http://image.zhangxinxu.com/image/blog/200908/png_btn.png); margin:-40px 0 0;” /></div>所显示的结果就是“首页”这个按钮鼠标经过的状态。通过margin控制图片的位置,由于父标签高宽以设定且溢出隐藏,所以就可以通过对图片的定位实现类似于background-position控制的效果。absolute绝对定位与margin定位其实是一样的,都是定位,应用的css属性不同而已。

b.如果您使用的是传统的JavaScript使得png透明,那么写法可以自由些。<img loading=”lazy” src=”https://image.zhangxinxu.com/image/blog/200908/png_btn.png” />的写法也是可以的,其定位与上面是一样的,直接通过设定class用css控制即可,一般不会出现莫名的错误的。

c.如果您使用的是jQuery png透明插件,则问题似乎不那么简单的。原版的jQuery png透明插件使用页面上定位解决background-position不起作用的问题是由局限性的。例如出现overflow:hidden失效的问题,img标签不受控制的问题,无法使用绝对定位的问题。我对其插件代码简单分析了下,找到上述问题的原因,并对原来的JavaScript代码做了些修改,使其支持页面上的类似background-position的定位效果。所以建议您下载修改后的png插件js。
另外,这里img标签失效是由于此插件处理透明的原理是,将原来的img标签隐藏,用一个span标签获取img标签的相关样式属性,将src链接的png图片以background-image的形式表示,并应用png透明滤镜。也就是说,代码执行的结果是将img标签换成span标签。所以如果您通过img标签控制图片的位置大小或是其他什么属性都是徒劳的。解决方法是用id或class进行控制,您给img标签赋一个class,例如”png_pos”,则插件执行后,这个class会转移到span标签上,所以对”png_pos”这个class设置的样式不会丢失,依旧在页面上表现出来,而且不会出现兼容性的问题。
下面这张图显示的就是页面定位后的效果图,支持hover事件,鼠标经过导航按钮按钮背景变化的效果,乍看去像是background-position定位的效果,实际上是在页面上使用margin定位的效果。

针对jQuery插件下png大图在页面上定位的问题,我特地写了一个演示页面,并提供源文件的打包下载。如果您手头上的就是IE6浏览器或您有IE6或以IE6为内核的浏览器,建议您狠狠地点击这里,里面有完整的代码示例说明,相信可能会对上面我不逃清楚的措辞有进一步的了解。

四、相关延伸的问题

1.png8与png24的透明显示
说了这么多IE6不支持png背景透明指的是png24格式保存的含有透明背景的图片,而以png8格式存储的png图片的全透明背景是支持的。一个支持而另外一个不支持的原因在于:png24的透明背景是Alpha透明背景,而png8格式的全透明背景是索引透明背景与gif的透明背景是同一个类型。

如下显示:

如果您使用的正是IE6浏览器,狠狠地点击这里进入demo实例页面

我曾经遇到过png图片的半透明层直接被css png透明滤镜当作完全透明层处理掉的情况。但是今天我反复尝试都没有出现这个情况,我想可能当时的png图片是用fireworks制作,保存的时候将图层分层信息也保存进去了。既然,没有再次出现这样的问题,自己也不宜多说,妄下定论。

所说IE6支持png8的背景透明,但是最终的图片效果跟gif的其实差别不太,都存在一个同样的问题,锯齿。就像上面这张图,所说png8格式的图片长得貌似还不错,水灵水灵的。只要是正好是个白色背景,而png默认也是白色锯齿的,一重合,正好就看上去不错了。可以要是是个深色背景,那就是白骨精遇见孙悟空——原形毕露啊。
png8图片献出原形后

有关锯齿的问题,我会单独写篇文章,这里先简单说个处理方法,例如上面的图片,背景色为#666666灰色时,png白色锯齿显露,解决方法是在photoshop保存图片的时候,将杂边的颜色设为跟背景色一致就行了,例如这里杂边颜色就设为#666666,
然后保存即可。
处理锯齿步骤一处理锯齿步骤二

2. IE7的alpha半透明滤镜与png背景透明
IE7 alpha半透明滤镜会影响其png24 Alpha透明通道的正常显示。下图为demo实例页面效果截图:

IE7下alpha滤镜对png透明的影响

图中可以看到本应透明显示的部分现在确是黑色的一团,怎一个“丑”字了得。

如果您有IE7浏览器,建议您将这个地址http://www.zhangxinxu.com/study/200908/ie7-filter-opacity-png.html放在IE7浏览器下看看,会有更加直观的体验与认识。

五、小结

IE6注定要退出历史舞台,但是目前国内的状况来看,比如网吧,都是IE6浏览器;我的一些刚接触电脑不久的亲戚也都是使用的IE6浏览器。IE8的出现蚕食的只是IE7的比重,对IE6对没有什么大的影响,所以这个退出的时间还真不好说,至少目前一段时间还是很有比重的,因此IE6下的些问题不得不拿出来说说,png透明的问题是非常典型的一个问题。这里我也只是将自己碰到的问题整理总结了一下,有些地方可能说得比较含糊,有些地方可能有遗漏,还有些则是不想展开的太多,乱了主线。不管怎样,算是博客的第一篇技术类的文章吧,断断续续也写了还几天,希望这些糟糕的文字和略显业余的实例页面能对大家有帮助。至少在写的过程中我是学到了不少的。共同进步吧!

(本篇完)

分享到:


发表评论(目前33 条评论)

  1. webwuyou说道:

    现在都是移动优先,ie基本淘汰了,还需要去兼容ie6吗?

  2. 张瑞说道:

    我试验了中间两种方法,先引了javascript的那个js文件,结果很奇怪,同样是img标签的png图片,有的有效果,有的就不行,还是没效果。然后我又引了jquery方法的js文件,这下倒好,直接一点效果也没有。两个js文件我是分开引用试验的。

  3. milan说道:

    第一种方法:IE css 滤镜,当包括滤镜样式的css外链文件与页面不在同一个目录下时,滤镜图片无法显示。楼主有办法解决吗?

  4. 静寂无闻之夜说道:

    实际使用都会有很多不知名的问题,尤其是配合定位这些。最恶心了

  5. 一月说道:

    说实话,看了你的文章,顿时心凉了半截,因为我全是用css sprite和png透明写的;
    如果全要换成margin或position,相当于重写一遍;
    绝望之余又上网搜了一下,幸亏找到一个可以同时支持css sprite和png透明的;
    http://www.enkj.com/help/newscontent/4379
    还是要感谢您的分享

  6. szr说道:

    用jquery实现去阴影 jquery的版本用1.4.4的可以 用1.7.2的js报错
    麻烦作者兼容一下

  7. 幼儿园说道:

    我试着用了..可是不灵啊!!

  8. linx4200说道:

    而且a刚好一边落在透明区域一边落在不透明区域
    点击透明区域部分的a可以相应
    点解不透明区域部分的a则不相应

  9. linx4200说道:

    我发现了一个问题…
    如果div背景png图片的透明区域相当大…
    而a包含在该div中而且位置落在透明区域中时…
    是可以响应单击事件的

  10. 鸣人说道:

    这篇文章写得不怎么样,ie6下png的背景完全没有解决,看起来还是那么的糟糕。

  11. 弧度零说道:

    14楼的情况我碰到了,还没解决,哪位高手遇到过解决了的啊,说下方法哦,谢谢!

  12. 我自轻狂说道:

    相当受用!最后我妥协了。该成8禁制的了。。。。哎,但动态加载其他页面时想同时用jquery做动画还没有头绪,,,,,,,,感谢!楼主新年快乐!

  13. 叶小倩说道:

    为什么我怎么试,一个都不行的呢

  14. 2年级说道:

    很详细,一直关注着你的教程,很实用

  15. nalanjia说道:

    微软发布了一个新的补丁,是针对VML的,打了之后再使用DD_belatedPNG.js
    PNG背景就会变成空的
    偶碰到了。。确实是

  16. super说道:

    关于png8的部分我想说一下作者理解的不正确,png8叫做调色板png,这个png关于透明有两种一种是二进制透明,也就是FW说的索引色透明,这种方式只有1或者是0也就是只有透明和不透明IE6对这个解析是正确的,这种png还有一种叫做a透明,也就是FW说的a透明,关于这种透明IE6也会处理可是有一些不一样,图片中间只要有透明的部分不管透明度是多少IE6自动渲染成全透明,没有透明度的部分渲染成不透明。

  17. peterhi说道:

    能否就IE6对png的行程原因说两句啊? 而且IE6 为什么把透明部分渲染成灰色啊? 那个颜色是可以设置的么?

  18. yuan说道:

    DD_belatedPNG_0.0.8a-min.js也可以处理IMG图片的,只要在引用JS时在参数里加上img这个词就行,用英文逗号隔开
    我一般都只写一个参数“.pngfix”,哪个元素用到PNG背景,就在那个元素上加class=”fixpng”,IMG图片上也可以这么加,这样参数里连IMG都不用加,很方便的,还不会多处理不需要处理的图片

  19. 前来报到说道:

    非常适应,太棒了

  20. web前端寒风说道:

    博主介绍的很全面,

  21. 风吹一笔说道:

    使用传统JS,会遇到一个问题,当网站其他很多地方用到PNG背景图,当那些背景图是用CSSsprite技术组合的大图时,会使网站布局发生动乱!IE6真够让人折磨的!

  22. 蹄子说道:

    我觉得可以增加一条有效的方式,即在web导出gif的时候选择256的颜色,默认的128的。

  23. riant说道:

    DD_belatedPNG_0.0.8a-min.js(压缩之后7Kb 大小) 这么优秀的东西,我以为大家都知道了呢,没想到还在折腾这么多方法,官方网站:http://www.dillerdesign.com/experiment/DD_belatedPNG/

    解决IE6 中 PNG 的background-position,background-repeat,可点击交互等问题,至于 img src=”…/xx.png” 这样引入的 png 图片 ,我没实践过——当然,作者说明处也说是支持的。

  24. 摇滚说道:

    从blogsearch搜到了这篇文章,真的很不错,希望能看到更多的新内容,已经订阅了rssfeed,祝博主好运:)

  25. 流浪者说道:

    很好,无意间发现,非常感谢。

  26. 李小鹏说道:

    你好,首先您的这篇文章写的真的不错,现在有一个问题,就是楼主用的jquery的方法并没有实现透明的效果,请楼主测试,我找了半天也没找到原因!

  27. actualist88说道:

    写的不错!非常不错!