Blue Skies Fading

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed mollis porttitor sem, eget iaculis massa fermentum ut.

Simple jQuery Cross-Fader Tutorial

HTML Source Code

The jQuery cross-fading banner requires the inclusion of two files. The first is called jqfader.js that contains the jQuery fader plug-in and calling code. The second is a CSS style sheet called jqfader.css that contains a number of styles that dictate the layout of the sliding banner and the addtional captions panel.

<link rel="stylesheet" type="text/css" href="jqfader/jqfader.css" />
<script type="text/javascript" src="jqfader/jquery.min.js"></script>
<script type="text/javascript" src="jqfader/jqfader.js"></script>

Some effort has been made with the HTML code to ensure that the page is still presentable even if JavaScript / jQuery is not available. When the jQuery code is not executed, the result is a static banner image with a single caption panel. The buttons are hidden using the CSS property visibility : hidden.

Once the jQuery is executed, the CSS visibility property of the buttons is changed to visible and the link URLs are used for the ccross-fading banner images. The link text is used as the caption heading and the title attribute content is used as the caption text. The order of the sliding images is affected by the order of the links within the unordered list.

<div id="wsnfader">
	<img src='images/banner1.jpg' alt='' />
        <div class="caption">
            <h3>Title 1</h3>
            <p>Caption 1 here</p>
	<ul class="buttons">
		<li><a href="images/banner1.jpg" title="Caption 1 here">Title 1</a></li>
		<li><a href="images/banner2.jpg" title="Caption 2 here">Title 2</a></li>
		<li><a href="images/banner3.jpg" title="Caption 3 here">Title 3</a></li>
		<li><a href="images/banner4.jpg" title="Caption 4 here">Title 4</a></li>
		<li><a href="images/banner5.jpg" title="Caption 5 here">Title 5</a></li>

A conscious decision was made to use a class attribute on the unordered list instead of an id attribute to avoid any potential conflicts with other HTML elements and to increase portability. The main container div has an id attribute of wsnFader, but this is never directly referred to from within the jQuery plug-in. If the id attribute of the container is changed, the calling code and the CSS styles can be updated to reflect this change.

CSS Source Code

The CSS styles required for the sliding banner are provided in a separate file called jqfader.css. Remember that if you change the name of the parent container's id attribute (default is wsnFader), that you also change the selectors in the CSS file to relect the change.

#wsnFader {
        width:800px;	/*Default user defined width*/
        height:240px;	/*Deafult user defined height*/
        font-family:Arial, Helvetica, sans-serif;

#wsnFader .buttons {
        margin:0 0 3px 0;
        visibility:hidden; /* Hide the buttons */

#wsnFader .buttons li {
        border:2px solid #000;

#wsnFader .buttons li a {

#wsnFader .buttons li a:hover {

#wsnFader .buttons li.current a {
#wsnFader .caption {
        background-color:rgba(0,0,0,0.7); /*opacity support for CSS3 browsers*/
#wsnFader .caption h3 {
#wsnFader .caption p {

jQuery Source Code

As this is an example of what can be done with jQuery, each line / block of code below has been commented. I am happy to answer any questions that you may have about the jQuery code and will accept any suggestions for improvements.

The basic principle behind the jQuery code is to use two images that can be cross-faded from 0% opacity (0.0) to 100% opacity (1.0) and vise-versa within a static viewport. The static viewport is defined by the div container that sits around all of the other banner elements. The CSS styles on the div limit the visible size of the container and allow elements that overflow this container to be clipped (hidden).

The two images start off positioned behind one another with the back image at 100% opacity and the front image at 0% opacity. At the specified interval, both images are animated to reverse their opacities using the jQuery .animate() method.

Once the images have finished fading, the front image's src attribute is then replaced with the href attribute of the 'current' link. The back image is reset behind the front image and is ready to be faded again.

(function( $ ){

//Define a method called wsnFader and accept a user defined 
//map of settings into a variable called 'options'.
$.fn.wsnFader = function(options) {    

//Supply a set of default values to use if not supplied.  
    var defaults = {   
            interval: 5000,
            speed: 800,
            slwidth: $(this).width(), 

    //Merge the supplied options with the plug-in defaults.  
    var settings = $.extend({}, defaults, options); 
    //Check user supplied wait interval and scroll speed settings.
    //If the speed is slower than the interval, change the speed to 
    //match the interval minus 100ms.
    if (settings.interval <= settings.speed) {
        settings.speed = settings.interval - 100;	

//Allow the plug-in to be part of a jQuery chain	
this.each(function() {

    //Store the current object reference so that we can pass it 
    //to other functions in tact.        
	var $this = $(this); 
    //Change the visibility of the buttons to visible.    

    //Hide the caption pane so that we can animate it into 
    //view. Change the solid colour of the pane to 70% opacity.

    //Add a class called 'current' to the first button
    //item to keep track of the current and next slides.   
    $('.buttons li:first').addClass("current");
    //Store the current buttons link href attribute so 
    //that we can pass it to other functions.
    var imgSrc = $('.buttons li.current a').attr("href");
    //The next 3 lines of code loop through the button links
    //and create an image tag for each behind the first image.
    //This is done purely to buffer the images on the page to 
    //prevent them from not appearing on slower connections.
    $('.buttons li a').each(function (i){
    	$this.append("<img src='" + $(this).attr("href") + "' class='buffer' />");
    	//For each link, move the link text into the alt 
        //attribute and overwrite it with the index 
        //number of the link. This will allow us to use
        //the alt attribute as the caption title of each slide.
        $(this).attr("alt", $(this).text()).text(i+1);
    //Create a duplicate of the first image to use when
    //sliding the images.                                  
    $this.prepend("<img src='" + imgSrc + "'/>");

    //Position the duplicate image behind the first image.
    $($this).find('img').not('.buffer').css({ position:"absolute", top:0, left:0 });
    //Use the JavaScript setInterval() function to call the 
    //nextSlide() function using the current reference and settings.
    //Let setInterval() call nextSlide repeatedly and use the 
    //settings.interval value as the delay.
    rotator = setInterval(function() {nextSlide($this, settings)}, settings.interval);

	//Next we need to capture the mouse clicks on the buttons.
    $('.buttons li a').click(function(evt) {
        //Capture and prevent the default link behaviour.	
		//Stop calling the rotator() function on an interval.
        //Grab the href attribute of the clicked on button.
        //We need this to change to the slide the user clicked on.
        var imgSrc = $(this).attr("href");

        //Store the title and captions from the alt and 
        //title attributes of the button clicked ($this).  
        var title = $(this).attr("title");
        var alt = $(this).attr("alt");
        //Find the back image and replace it's src attribute
        //with the clicked button's url 
        $($this).find('img').eq(1).attr("src", imgSrc).show(0);
        //Then fade out the front image to make the new image
        //visible. Once it is visible, replace the front image
        //src attribute as well and turn it back on using show().
        //Replace the caption title and text and then slide the 
        //caption down over 500ms.
        $($this).find('img').eq(0).fadeOut(100, function() {
            $($this).find('img').eq(0).attr("src", imgSrc).show(0);
            $('.caption h3').text(alt);
            $('.caption p').html(title);
        //Remove the 'current' class from all buttons.
        $('.buttons li.current').removeClass("current");
        //Add the 'current' class to the button the user clicked.
        //Restart the timer on the rotator with default interval.
        //This means that once a user clicks on a button they will
        //wait the default interval time rather than moving on.
        rotator = setInterval(function() {nextSlide($this, settings)}, settings.interval);

//Return the chained object reference to jQuery 
return this;	

//The nextSlide function will animate the sliding images 
//using the current object referenece in $this and the
//settings supplied by the user or the default values.
nextSlide = function ($this, settings) {

	//Within the referenced object, find the front image & set it's
    //default starting opacity to 0%.
    //Store the next item after the 'current' item.                    
    var nextImage = $('.buttons li.current').next();
    //If there is no next item, set the new current item as the
    //first item by adding the 'current' class to the first sibling.
    //If there is a next item, remove the 'current' class
    //and add it to the returned item.
    if (nextImage.length == 0) {
        $('.buttons li.current').removeClass("current").siblings(":first").addClass("current");
    } else {	
        $('.buttons li.current').removeClass("current").next().addClass("current");

	//Store the href attribute of the new current link
    var imgSrc = $('.buttons li.current a').attr("href");

 	//Store the title and captions from the alt and 
    //title attributes of the button with class 'current'.  
    var title = $('.buttons li.current a').attr("title");
	var alt = $('.buttons li.current a').attr("alt");

	//Find the front image and change it's src attribute to
    //the stored URL. Then animate the front image's opacity
    //to 100% using the speed from settings.
    $($this).find('img').eq(1).attr("src", imgSrc)
.animate({opacity:"1.0"},(settings.speed)); //Start by sliding the caption up out of view. Once this is //done execute the code within the anonymous function. $('.caption').slideUp(100, function () { //Find the back image and fade it out to 0% opacity. //Once the back image has finished fading, reset it and //populate the caption title and text fields. Finally, //slide the caption down so that it is visible. $($this).find('img').eq(0) .animate({opacity:"0.0"}, settings.speed, function() { $(this).attr("src", imgSrc).css({opacity:"1.0"}); $('.caption h3').text(alt); $('.caption p').html(title); $('.caption').slideDown(500); }); }); }; //End the plug-in code })( jQuery ); //Call the jQuery plug-in on any item with an //'id' attribute of 'wsnFader'; //Some settings have been supplied as a map object. $('document').ready(function () { $('#wsnFader').wsnFader({interval:6000, speed:300}); });

jQuery Course Trainer

Bjorn has been involved in CSS based web design for nearly 10 years and has experience developing web applications in both small and large teams of developers.

Over the past few years he has closely followed the evolving standards for web development and has spent countless hours discussing appropriate markup with web designers in the industry. He has also run training courses on web standards and accessibility which stems from his vast experience with CSS web design.

Follow Bjorn on Twitter