opacity for fades · 17 October 2007, 16:52
By default, I browse the internet with JavaScript and Flash turned off. Still, I greatly prefer JavaScript to Flash… and not because JavaScript and JScript are variants of the open standard ECMAScript, though I’m sure that many people will view this as a considerable ‘pro’. The reason is simple… in 9 of 10 cases, JavaScript does the job… and no one has to download a plug-in for it. There’s nothing more annoying that people who code their page to need Flash, and then just use it for the simplest things.
As such, when I was asked to make a crossfading slideshow, I wanted to see if I could coax JavaScript into the same.
How to
The keyword is opacity.

If I were to change an element’s opacity, it would stand to reason that whatever was behind it would be alpha-blended into it. The trick? This also applies to background images.
In regards to mark-up, you need to add a containing element around your image that can take a background image. Unless you have something specific in mind, you probably want to use a simple div tag.
Now you’re almost set to go. Almost.
For browser compatability purposes, you’ll want to start you script off with something that you, if you code JavaScript frequently, probably use a lot anyway: a declaration of getElementById() in those instances where it is amiss.
My variant thereof is a no doubt ugly mixture of a ton of internet methods and the principle of object detection taken to heart, but as it works, I’m going to share it. May the more experienced amongst you have mercy on my soul.
// Check if getElementById exists. If not, declare it to mean something we DO have access to:
if (!document.getElementById) {
if (document.all) {
document.getElementById = function() {
if (typeof document.all[arguments[0]] != "undefined") {
return document.all[arguments[0]];
} else {
return null;
}
}
} else if (document.layers) {
document.getElementById = function() {
if (typeof document[arguments[0]] != "undefined") {
return document[arguments[0]];
} else {
return null;
}
}
} else {
// No alternative found.
document.getElementById = function() {
return null;
}
}
}
Now that document.getElementById() has been defined whether it existed in that fashion or not, we can use it to address our mark-up that’s intended for our script.
But things don’t end there.
Internet Explorer 6 (whether you loathe it or not, it’s still around) doesn’t support the CSS property opacity. Does that mean it’s out of the loop? No. Actually, it’s a lot easier to do fades in IE6 than in other browsers, which is why so many of the solutions on slideshow fades you find online are only pretty for Internet Explorer.
Instead of support the opacity style, IE6 (and presumably IE5) supports filters. Filters are a powerful means of manipulating graphics that register not as CSS but as scripts, like JavaScript, despite their placement – but right now, we’re just interested in alpha(). As the name suggests, alpha() lets you give an object an alpha value, which is just what we need.
Unfortunately, my solution lacks elegance at this point. I’m not sure how to use object detection to make sure that only the one or other value is set. Granted, IE6 ignores opacity, and all other browsers ignore filter, but I have an uncanny feeling that IE7 might end up doing double the work this way.
// Change an object's opacity
function changeOpacity(obj,opacity) {
obj.style.opacity=opacity;
obj.style.filter = "alpha(opacity="+(opacity*100)+")";
return true;
}
Beyond that, you’ll want something akin to the following*:
var opacity = 1;
function fadeIn() {
// retrieve image and background image objects
var obj = document.getElementById('test');
var wrap = document.getElementById('wrap');
// calculate new opacity
opacity = new_opacity_value(opacity);
// make the change
changeOpacity(obj,opacity);
// if the crossfade has completed, swap images
if (opacity==1) {
// kept simple, but this could obviously iterate across an array of images, too
wrap.style.backgroundImage = "url(picture1.png)"; // previously obj.src
obj.src = "picture2.png"; // previously hidden
}
// repeat function call ever 0.2 seconds
window.setTimeout("fadeIn()",200);
}
You’ll have to define how your opacity value changes in a function called new_opacity_value(). In case of a slideshow, you’ll probably want it to decrement gradually, not dropping below 0 in the process – and when it has hit 0, set it back up to one. This might be what you want, for example*:
function new_opacity_value(opacity) {
if (opacity<=0) {
return 1;
} else {
return max(opacity-0.1,0);
}
}
Those are the building blocks you’ll need to make your slideshow. I don’t currently have a slideshow script which just requires that you change an array, but even though I’d like to put one up, if just for illustrative purposes, please don’t hold your breath. This article is meant to give you the building blocks – not a tailored solution.
The disaster
Depending on what system and in what configuration you’re running Internet Explorer 6 on when looking at the resulting page through it (if at all), you may notice a ghastly flickering.
This is the famous CSS background image flicker that has been beaten to death on various websites. It took me a while to find it, since I assumed it was a JavaScript error, rather than a CSS one, but I finally found something that beats the subject to death in admirably thorough ways. Interestingly enough, while that page did refer to something that removed the flicker (I’m referring to the solution involving .htaccess), IE6 would still make the cursor flick from hand-cursor to normal cursor over links while the script ran. As such, not the ideal solution.
But the person who supplied that fix in turn has since discovered another page referring to a JavaScript solution to the IE background flicker problem. For ease of reference, here’s the solve-all and fix-all (note that the snippet has to be placed between your page HEAD tags.):
try {
document.execCommand("BackgroundImageCache", false, true);
} catch(err) {}
And that works like a charm.
Footnote: * denotes untested code snippets.
— Neike Taika-Tessaro
Comment
| Categories: | css , development , javascript , knowledge |
|---|---|
| Related: | Beating a dead horse: Jurassic Park raptors · 27 December 2008, 03:23mIRC Script: Opping yourself in all channels in a single go · 14 December 2008, 21:48mIRC Script: Flexible moderation · 14 December 2008, 21:27mIRC cut script · 8 December 2008, 09:22Global variables in PHP · 17 October 2007, 17:35 |