Image Cross Fade

Posted on by

Today’s DHTML trick is a smooth example of Image Cross Fading. The Javascript code for the whole page is rather short to begin with, but there was some rom for improvement. If you were to look at the original source file, just about everything except for the variable declarations and the so_xfade method can be reduced to this snippet, using jQuery:

$(document).ready(function(){
  $("head").append("<link href='xfade2.css' \
    rel='stylesheet' type='text/css'>");
  img = $("#imageContainer img").set("xOpacity",0).get();
  $("#imageContainer img:first").set("xOpacity",0.99).show();
  setTimeout(so_xfade,1000);
});

Currently, there doesn’t seem to be a more elegant way of doing it in jQuery, but I can’t really complain, considering how much more understandable the code is, compared to doing it the DOM way.

10 thoughts on “Image Cross Fade

  1. Heh, you’re at it again with the technique-of-the-day translated into jQuery.

    Quick request: When the page is first loaded, the long list of images flashes up for a second. That’s ugly, and probably unnecessary. Maybe improve the original script to eliminate it?

  2. I think the problem stems from the fact that the author is dynamically writing the stylesheet into the header – meaning that the batch of style information isn’t interpreted until much later (after the DOM tree has already been parsed). If I had to recommend a fix, it would be to just have the stylesheet in your header, as normal, instead of doing it dynamically. I haven’t tested this theory yet, but it seems most logical.

  3. The flash of images is easily fixed by not writing the new css file to the page and just hiding the images with the original stylesheet.
    However, the problem with this is if I’m in a user agent without javascript but with CSS, the document becomes broken since only the first image will appear for the user.

    So, the trick is how to avoid the flash of unstyled content, but maintain accessibility. Possibly a setTimeout that checks for the existance of the container element every nth second and when it has becomes a part of the DOM it sets its overflow to hidden, but even that might not work *every* time.

    I leave it to the user of the code to decide how they want it to behave. display:none; in the CSS is not a difficult addition for anyone.

  4. Steve: The setTimeout trick should work. I’ve used it before in other settings to achieve this effect, and it was what I was originally thinking of as the best way of getting around the issue.

  5. I’ll have to agree with Bob about the technique-of-the-day posts; it’s really neat. Do you take requests? :-)

    I’ve been dragging my feet about implementing a more generic fold/unfold comments framework that could be used to neatly zip away content in levels. On the other hand, I suppose that is the kind of code you don’t get much help from any library to implement, as it’s more page logic than DOM twiddling.

  6. Johan: I don’t see why I couldn’t give the fold/unfold thing a try – I’ll see if I can give it a whirl, if I have some extra time this weekend.

  7. abba bryant on said:

    I am rather curious. Is there any reason you couldn’t use Dean Edwards
    Body onload solution
    method to call a function that would do this when the dom was ready but sooner than the Ready() function call you do now?

    Something like…(at work and can’t really test this)

    function init() {
       if (arguments.callee.done) return;
       arguments.callee.done = true;
       img = $(“#imageContainer img”).set(“xOpacity”,0).get();
       $(“#imageContainer img:first”).set(“xOpacity”,0.99).show();
       setTimeout(so_xfade,1000);
    };
    if (document.addEventListener) {
       document.addEventListener(“DOMContentLoaded”, init, null);
    }
    // for Internet Explorer //
    //@cc_on @//
    //@if (@_win32)
       document.write(“[script defer src=ie_onload.js][“+”/script]”);
    /@end @//
    /* for other browsers */
    window.onload = init;

    ******

    where the ie_onload.js external script simply contains the line
    init();

    ******

    I take no credit at all for this and would like to restate that I am a js newb and not capable of even trying this from where I am.

    If this does work.. is there any hope of a DOMReady() function that would implement this for IE / FF and hand the code off to the Ready() function if conditional compilation or DOMContentLoaded is not available?

    Abba

    NOTE : The conditional compilation comments are wrong. The comment form wouldn’t allow them in. Same for the [ & ] characters in the script block.

  8. Abba: The advantage to using the current method is that it’s still really really fast – and it’s that fast in all modern browsers (Opera and Safari included).

    Although, including the custom code for IE and FF (to be guaranteed to work) might be a good idea. I’ll keep this in mind.

  9. Phillip Oldham on said:

    I’ve tried using this code, and I seem to get a “jump” between the first image and second image before the actual fade effect kicks in. Any way to remove this?