Cross-Browser Variable Opacity with PNG

Periodically, someone tells me about the magic of PNG, how it's the ideal image format for the web, and that someday we'll all be using it on our sites instead of GIF. People have been saying this for years, and by now most of us have stopped listening. Sadly, flaky browser support has made PNG impractical for almost everything; but now, with a few simple workarounds, we can finally put one of its most compelling features to use.

PNG? What?

The Portable Network Graphics, or PNG (pronounced “ping”), image format has been around since 1995, having cropped up during the now long-forgotten GIF scare, when Compuserve and Unisys announced they would begin charging royalties for the use of the GIF image format.

To provide GIF support in their applications, software makers like Adobe and Macromedia must pay royalty fees – fees which are passed down to the end user in the selling cost of the software.

When PNG appeared on the scene, web designers were ready to make the switch to the free, superior format and shun GIF forever. But over time, browsers continually failed to support PNG, and eventually most people started to forget about it. Today, nearly everyone still uses GIF habitually.

Which is a shame, because PNG makes GIF look pretty pathetic: it supports gamma correction, (sometimes) smaller file sizes, loss-less compression, up to 48-bit color, and, best of all, true alpha transparency.

To get why alpha transparency is a big deal, we must first understand one of the most annoying limitations of GIF.

Binary Transparency: the Scourge of GIF

When it comes to transparency, GIF doesn't cut it. Whereas PNG supports alpha transparency, GIF only supports binary transparency, which is a big limitation and has a couple of important implications.

For one, a GIF image can either use no transparent colors at all or have one color that's completely transparent – there are no degrees of transparency.

And if a complex GIF does contain a transparent color, the background color of the web page must match the transparent color, or else the anti-aliased area around the transparent color will be surrounded by ugly haloing and fringing. If you've spent more than five minutes as a web designer, you know what I'm talking about.

The result is that any anti-aliased transparent GIF is inextricably tied to the background color of the web page on which it lives. If you ever decide to change that color, you must also change the GIF.

Miraculously, PNG doesn't behave that way. A PNG can be transparent in varying degrees – in other words, it can be of variable opacity. And a transparent PNG is background-independent: it can live on any background color or image. Say you want your navigation on monkeys-run-amuck.com to be 65% opaque so you can see through it to your orangutan background image. You can do that. A transparent anti-aliased “Gorillas, Chimps, Gibbons, et al” title that can sit on top of any background color or image? You can do that, too.

So What About Browser Support?

By now, of course, we'd all be up to our ears in PNGs if browsers supported them reliably. But seven years after the format's inception, you still can't slap a PNG onto a web page like you can a GIF or JPG. It's disgraceful, but not as bad as it sounds.

It turns out that most of the latest versions of the major browsers fully support alpha transparency with PNG – namely, Netscape 6, Opera 6, and recently-released Mozilla 1, all on Windows; and, for the Mac, Internet Explorer 5, Netscape 6, Opera 5, Mozilla 1, OmniWeb 3.1, and ICab 1.9. Incredibly, PNG even works on Opera 6 for Linux, on WebTV, and on Sega Dreamcast.

Now, what's missing from that list?

IE5.5+/Win, bless its heart, will, in fact, display a PNG, but it doesn't natively support alpha transparency. In IE5.5+/Win, the transparent area of your PNG will display at 100% opacity – that is, it won't be transparent at all.

Bugger. So what do we do now?

Proprietary Code-o-Rama: the AlphaImageLoader Filter

IE4+/Win supports a variety of non-standard, largely ridiculous visual filters that you can apply to any image's style. You can, for instance, fade in an image with a gradient wipe, or make it stretch from nothing to full size, or even make it swipe into place circularly, like a scene change in Star Wars.

A non-pointless gem among these is the AlphaImageLoader filter, which is supported in IE5.5+/Win. When used to display a PNG, it allows for full alpha transparency support. All you have to do is this:

<DIV ID="myDiv"
STYLE="position:relative;
height:250px;
width:250px;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader»
(src='myimage.png',sizingMethod='scale');"></DIV>

(Line wraps are marked ». –Ed.)

And you're in business. Perfect alpha transparency. This code works great, with only the small drawback that it's not part of any accepted web standard, and no other browser on the planet understands it.

Serving up PNGs with JavaScript

So the trick is to determine the user's browser and serve up the images appropriately: if IE5.5+/Win, then we use AlphaImageLoader; if a browser with native PNG support, then we display PNGs the normal way; if anything else, then we display alternate GIFs, because we can't be sure that a PNG will display correctly or at all.

Using a slightly tweaked version of Chris Nott's Browser Detect Lite, we set some global variables to this effect that we can use later on.

// if IE5.5+ on Win32, then display PNGs with AlphaImageLoader
if ((browser.isIE55 || browser.isIE6up) && browser.isWin32) {
var pngAlpha = true;
// else, if the browser can display PNGs normally, then do that
} else if ((browser.isGecko) |»
| (browser.isIE5up && browser.isMac) |»
| (browser.isOpera && browser.isWin »
&& browser.versionMajor >= 6) |»
| (browser.isOpera && browser.isUnix »
&& browser.versionMajor >= 6) |»
| (browser.isOpera && browser.isMac »
&& browser.versionMajor >= 5) |»
| (browser.isOmniweb && »
browser.versionMinor >= 3.1) |»
| (browser.isIcab && »
browser.versionMinor >= 1.9) |»
| (browser.isWebtv) |»
| (browser.isDreamcast)) {
var pngNormal = true;
}

(Note for the faint of heart: complete source code for all the examples we cover is available at the end of the article.)

Tactic 1: Quick and Dirty with document.writes

The simplest, most reliable way to spit out PNGs is using inline document.writes based on the above detection. So we use a function like this:

function od_displayImage(strId, strPath, intWidth, »
intHeight, strClass, strAlt) {
if (pngAlpha) {
document.write('<div style="height:'+intHeight+'px;»
width:'+intWidth+'px;»
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader»
(src=\''+strPath+'.png\', sizingMethod=\'scale\')" »
id="'+strId+'" class="'+strClass+'"></div>');
} else if (pngNormal) {
document.write('<img src="'+strPath+'.png" »
width="'+intWidth+'"»
height="'+intHeight+'" name="'+strId+'" »
border="0" class="'+strClass+'" alt="'+strAlt+'" />');
} else {
document.write('<img src="'+strPath+'.gif" »
width="'+intWidth+'"»
height="'+intHeight+'" name="'+strId+'" »
border="0" class="'+strClass+'" alt="'+strAlt+'" />');
}
}

Now we can call the od_displayImage function from anywhere on the page. Any JavaScript-capable browser will display an image, and, if we want to be really careful, we can accompany each call with a <noscript> tag that contains a regular <img> reference. So the respectable browsers get PNGs normally, IE5.5+/Win gets them with the filter, and all other browsers get regular GIFs, whether they have JavaScript turned on or not.

It's a time-tested method, but what if we want more control over our PNGs?

Tactic 2: the Beauty & Majesty of Objects

When I told the programmer in the office next door that I was writing this article, he took one look at my code, glowered at me, and said, “Fool. Where's the abstraction? You need to use objects.”

So now we have a JavaScript object to display PNGs. Here's how we use it:

<html><head>
<script language="javascript"
src="browserdetect_lite.js"
type="text/javascript">
</script>
<script language="javascript"
src="opacity.js"
type="text/javascript"></script>
<script type="text/javascript">
var objMyImg = null;
function init() {
objMyImg = new OpacityObject('myimg','/images/myimage');
objMyImg.setBackground();
}
</script>

<style type="text/css">

#myimg {
background: url('back.png')
repeat; position:absolute;
left: 10px; top: 10px;
width: 200px;
height: 200px;
}

</style>

</head>

<body onload="init()" background="back.jpg">

<div id="myimg"></div>
</body>
</html>


That's it. The cool thing about the OpacityObject is that we just pass it a DIV ID and an image path and we're done. Using the appropriate technique, it applies the image as a background of the DIV, and from there we can do whatever we want with it. Fill it with text, move it across the screen, resize it dynamically, whatever – just like any other DIV.

The object works in any CSS 1-capable browser that can dynamically apply a background image to a DIV with JavaScript. It's completely flexible, and we could even use it in place of the above function.

The trade-off is that it doesn't degrade as nicely. Netscape 4.7/Win/Mac and Opera 5/Mac, for instance, won't display an image at all. And it has another significant problem, which is this:

IE5/Mac only supports alpha transparency when the PNG resides in an <img> tag, not when it's set as the background property of a DIV. So PNGs displayed with the OpacityObject will appear 100% opaque in IE5/Mac. This problem is especially frustrating because IE5/Mac is the only browser which natively supports PNG and behaves this way. We've notified Microsoft about this apparent bug and hope for it to be fixed in an upcoming release.

But for now, these issues are the trade-off for flexibility. Obviously, choose the right tactic based on the particular needs of your project. Between them both, you can do pretty much anything with PNGs – like, for instance...

Example 1: Translucent Image on a Photo

In this simple example, we see how the same 80% opaque PNG can be displayed on any kind of background: Translucent Image on a Photo.

Example 2: Anti-Aliased Translucent Navigation with Rollovers

What a beautiful thing it would be, I'm sure you've thought from time to time, to create translucent anti-aliased images that work on any background. Well, check it out: Anti-Aliased Translucent Navigation with Rollovers.

Mouse over the images, observe the behavior of the rollovers, and click “change background” to see how the images behave on different backgrounds. Then view the source. There are a few things worth noting here:

  • To preload the correct images, we create a variable called strExt, which contains either “.png” or “.gif.” As long as our PNGs and alternate GIFs use the same names except for the file extension, the browser will only preload the images that it's actually going to use.
  • We create a class called pngLink and set the cursor property to “pointer.” We pass that class name to the function when we call it, and the function applies the class to the PNG. The result is that the user's pointer turns into a cursor when he rolls over the image links, even though, in IE5.5+/Win, they're really just DIVs. (You might also want to add "display:block" or "display:inline" to your PNG class, depending on how you're using the images, to make them display correctly in Netscape 6. (For details, see Better Living Through XHTML.)
  • We also use a couple of rollover functions specifically for displaying PNGs. It turns out that, while it's possible to dynamically swap out PNGs using the AlphaImageLoader, IE5.5+/Win has a tough time of it; it's damn slow, too slow for effective rollovers. What works better is to apply a background color to the DIV that contains the PNG – the color will shine through the transparent part of the image, and do it fast, too. When we call the function, we send along the name of the image to be displayed and an HTML color – IE5.5+/Win will display the color, and the others will display the image.
  • Notice how those images even have drop shadows. You could stick any background image or color behind them and they would still look great, even if the PNGs were completely transparent. Is that cool or what?

Example 3: Floating Translucent DIV with HTML Text Inside

In the first two examples, we used the quick-and-dirty function from tactic one. Now, we want our PNG to interact with other code on the page, so this time we display it with the OpacityObject.

But remember – there are drawbacks to this approach (see above), the most heartbreaking of which is that this example doesn't work perfectly on IE5/Mac. If that causes you pain, then there's always the quick and dirty function. Otherwise, read on.

First we create a DIV, give it an ID, and assign any style properties we want to it – height, width, font family, etc.

Then we pass along the ID of that DIV when we instantiate the OpacityObject. We pass along the image path, too, and now we have a DIV with a translucent background. Cool!

Next we put some HTML text in the DIV and apply another unrelated object method to it (this object has nothing to do with the OpacityObject – it could be any code you have lying around). Now we can move the translucent DIV around the screen. Wheee! Floating Translucent DIV with HTML Text Inside.

So there's a glimpse of what's possible with the OpacityObject. You hardcore CSS/DOM folks, go nuts.

Variably Opaque-R-You

Download the source code for the object, functions, and examples we covered. All the code relies on our tweaked version of Browser Detect Lite, which is included as well. Variable Opacity Source Code.

One PNG and One PNG Only

This is all very exciting, but, as with many achievements that get web developers excited, making PNG work in today's browsers simply shouldn't be this hard. You might consider signing the petition to persuade Microsoft to provide full PNG support in Internet Explorer. With any luck, this article will soon be obsolete.

In the meantime, post any ideas for improvements to this code in the discussion forum for this article. The PNG home site, for instance, talks about a few other obscure browsers that should support alpha transparency, but that haven't been verified yet. If you can verify any of these claims, or have any other valuable input, let us know, and we'll update the code accordingly.

Resources


(0)

相关推荐

  • js+CSS实现弹出居中背景半透明div层的方法

    本文实例讲述了js+CSS实现弹出居中背景半透明div层的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999

  • CSS opacity - 实现图片半透明效果的代码

    前几天一位做网页设计的朋友问我这个问题:如何通过CSS来实现图片半透明效果,并且在IE和Mozilla上都可以得到支持.下面将我的方法分享给大家. 下图为通过CSS实现的图片透明效果 这个效果在IE和Mozilla浏览器上都可以工作,代码如下 <img alt="powerbookg4.jpg" src="archives/images/powerbookg4.jpg" width="250" height="60" s

  • 纯JS半透明Tip效果代码

    Test function opacity(id, opacStart, opacEnd, millisec) { //speed for each frame var speed = Math.round(millisec / 100); var timer = 0; //determine the direction for the blending, if start and end are the same nothing happens if(opacStart > opacEnd)

  • IE6下opacity与JQuery的奇妙结合

    复制代码 代码如下: <!doctype html><html><head><meta charset="utf-8"><title>无标题文档</title><script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js">&l

  • Opacity.js

    复制代码 代码如下: //---------------------------------------------------------------  // Opacity Displayer, Version 1.0  // Copyright Michael Lovitt, 6/2002.  // Distribute freely, but please leave this notice intact.  //-------------------------------------

  • 原生js实现半透明遮罩层效果具体代码

    复制代码 代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv=&qu

  • js和jQuery设置Opacity半透明 兼容IE6

    1.css设置透明度 透明度在IE浏览器和其他相关浏览器中的设置方法是不一样的,IE使用滤镜filter的alpha属性,firefox和其它浏览器不支持滤镜,它们使用opactiy属性设置透明度,下面示例设置透明度为30%: IE:filter: alpha(opacity:30): firefox:opacity(0.3): 2.使用js设置透明度 为了兼容IE与其他浏览器对透明度的设置,我们需要对以上两种样式分别进行设置.下面是一段示例代码: 复制代码 代码如下: var alpha =

  • Cross-Browser Variable Opacity with PNG

    Periodically, someone tells me about the magic of PNG, how it's the ideal image format for the web, and that someday we'll all be using it on our sites instead of GIF. People have been saying this for years, and by now most of us have stopped listeni

  • 学习从实践开始之jQuery插件开发 对话框插件开发

    前言: 之所以写下这篇文章,是想将我的想法分享给大家:对于初学者,我希望他能从这篇文章中获取对他有用的东西,对于经验丰富的开发者,我希望他能指出我的不足,给我更多的意见和建议:目的就是共同进步. 一.要做什么插件? 我想要实现一个插件可以取代浏览器默认的弹出对话框或窗体,就是我们通过调用window.alert,window.confirm,window.prompt这些方法 所弹出的网页对话框,通过调用window.open,window.showModalDialog,window.show

  • 无js5款纯div+css制作的弹出菜单标准

    一.最基本的:二级dropdown弹出菜单 二级dropdown弹出菜单--A CROSS BROWSER Drop DOWN CASCADING VALIDATING MENU /* common styling */ /* set up the overall width of the menu div, the font and the margins */ .menu { font-family: arial, sans-serif; width:750px; margin:0; mar

  • Div+Css(+Js)菜单代码及制作工具

    效果直逼flash的Div+Css+Js菜单 css菜单 body{ background-color:#B8B8A0; } #fbtn{ display:none; overflow:hidden; border-style:solid; border-width:1px; border-color:#e1e1c9 #e1e1c9 #6e6e56 #6e6e56; padding:1 1 1 1; width:115px; height:30px; } #fbtn_txt{ position:

  • 22个国外的Web在线编辑器收集

    1. TinyMCE 免费,开源,轻量的在线编辑器,基于 javascript,高度可定制,跨平台. 2. FCKEditor 免费,开源,用户量庞大的在线编辑器,有良好的社区支持. 3. YUI Editor 属于 Yahoo! YUI 的一部分,能输出纯净 Xhtml 代码. 4. NicEdit 简单,易用,轻量,外观漂亮的在线编辑器. 5. Kupu 开源,支持 ajax 保存,跨平台,易于集成,由 OSCOM 推出. 6. Free Rich Text Editor 非常容易部署,输出

  • js实现获取div坐标的方法

    本文实例讲述了js实现获取div坐标的方法.分享给大家供大家参考,具体如下: html中最常使用的控件就是div了,那么如何获取div的坐标呢? 如下方法可以实现: /*** * 获取div的坐标 * @param divObj * @returns {{width: number, height: number, left: *, top: Window}} */ com.whuang.hsj.divCoordinate=function(divObj){ if(typeof divObj =

  • php广告加载类用法实例

    本文实例讲述了php广告加载类的用法,非常实用.分享给大家供大家参考.具体方法如下: 该php广告加载类,支持异步与同步加载.需要使用Jquery实现. ADLoader.class.php类文件如下: <?php /** 广告加载管理类 * Date: 2013-08-04 * Author: fdipzone * Ver: 1.0 * * Func: * public load 加载广告集合 * public setConfig 广告配置 * private getAds 根据channel

  • Javascript中的var_dump函数实现代码

    发现了一个非常好的JavaScript调试方法,目前看到的是可以打印Object/Array/Function/String四种类型,使用方法和PHP中的var_dump()一样,只要直接dump(变量名)即可. 复制代码 代码如下: dump(value, [showTypes]) @ param value (Any) value to dump @ param [showTypes] (Boolean) optional to display each key/value's type @

  • Firefox outerHTML实现代码

    减少DOM数可以加快浏览器的在解析页面过程中DOM Tree和render tree的构建,从而提高页面性能.为此我们可以把页面中那些首屏渲染不可见的部分HTML暂存在TextArea中,等完成渲染后再处理这部分HTML来达到这个目的. 要把TextArea 中暂存的HTML内容添加到页面中,使用元素的outerHTML属性是最简单方便的了,不过在DOM标准中并没有定义outerHTML,支持的浏览器有IE6+,safari, operal和 Chrome,经测试FF4.0- 中还不支持.所以我

  • 推荐15个最好用的JavaScript代码压缩工具

    JavaScript 代码压缩是指去除源代码里的所有不必要的字符,而不改变其功能的过程.这些不必要的字符通常包括空格字符,换行字符,注释以及块分隔符等用来增加可读性的代码,但并不需要它来执行. 在这篇文章中,我们选择了15个最好用的 JavaScript 压缩工具,有简单的在线转换器,GUI工具和命令行界面等. 1. JavaScript Minifier It is a nice looking tool with an API to minify your js code. 2. JSMIn

随机推荐