Create an infinite polaroid image viewer with jQuery


The name of the tutorial might be a bit confusing, so I’ll start by clearing it up.

Infinite – Refers to the fact that if you click the “next button” on the last slide, it loops to the first image, and vice-versa with the “previous button”. (Achieved with jQuery javascript)
Polaroid – Refers to the look (achieved with CSS)
Image Viewer – I was going to use “Carousel”, however, this doesn’t really slide… It fades. So “Image Viewer” found a place in the title. (Achieved with jQuery javascript)

I like image/content sliders, however, they are always so complicated: Divs within divs containing unordered lists, list items, anchor links and span tags.
This Infinite Polaroid Image Viewer works on a single div containing <img> tags. The caption text is taken from <img> alt tags. Also, this is designed to look decent without CSS3 and with javascript turned off.

Let’s get started.

The HTML

What exactly is needed besides the div#polaroid?
Yes, you guessed it, the controls and caption area. The caption area is not necessary without javascript (since this won’t work at all without it) so it would be best to inject it using javascript. It is added in the HTML below, however we will remove it at a later stage to minimize the markup.

<div id="polaroid">
	<img alt="People at a bar" src="images/image-1.jpg" />
	<img alt="Tree and Dam" style="display: none;" src="images/image-2.jpg" />
	<img alt="Puppy" style="display: none;" src="images/image-3.jpg" />
	<img alt="Clouds" style="display: none;" src="images/image-4.jpg" />
</div>
<div id="polaroid-caption">
      <a id="prev" href="#"></a>
      <a id="next" href="#"></a>
      <p class="caption"></p>
</div>

I don’t think we could work with much less markup, and because of this, there really much to explain about the HTML. It’s very straightforward:
We will be able to cycle through the images included within the #polaroid div.

The CSS

We’re going to do the obvious styling with the CSS, including some CSS3 and a fall-back in case javascript is turned off.
We’ve added some inline styling to the images in the HTML. This is done to make sure only one image is shown if the javascript is turned off.

#polaroid{
	background: #ededed;
	margin: 0 0 0 20px;
	padding: 15px 15px 0 15px;
	width: 500px;
}
#polaroid img{
	width: 500px;
	height: 380px;
}
#polaroid-caption{
	color: #000;
	background: #ededed;
	height: 40px;
	margin: 0 0 0 20px;
	padding: 30px 15px;
	width: 500px;
}

/* Caption and controls */
#polaroid-caption a{
	color: #000;
}
#polaroid-caption p.caption{
	font-weight: bold;
	text-align: center;
}
#prev, #next{
	display: block;
	height: 24px;
	width: 14px;
}
#prev{
	background: url(../images/prev.jpg) no-repeat left top;
	float: left;
}
#next{
	background: url(../images/next.jpg) no-repeat left top;
	float: right;
}

/* css3 */
#polaroid{
	border-top-left-radius: 10px;
	border-top-right-radius: 10px;
	-moz-border-radius-topleft: 10px;
	-moz-border-radius-topright: 10px;
	-webkit-border-top-left-radius: 10px;
	-webkit-border-top-right-radius: 10px;
}
#polaroid-caption{
	border-bottom-left-radius: 10px;
	border-bottom-right-radius: 10px;
	-moz-border-radius-bottomleft: 10px;
	-moz-border-radius-bottomright: 10px;
	-webkit-border-bottom-left-radius: 10px;
	-webkit-border-bottom-right-radius: 10px
}

The jQuery Javascript

Alright, now it’s time for the cool part javascript:

$(window).load(function(){ 

	$("#polaroid").after('<div id="polaroid-caption"><a id="prev" href="#"></a><a id="next" href="#></a><p class="caption"></p></div>');

	$("p.caption").text($("#polaroid img:visible").attr("alt"))

	// Next controls
	$("#next").click(function(){
		if($("#polaroid img:last").is(":visible")){
			$("#polaroid img:visible").fadeOut(function(){
				$("#polaroid img:first").fadeIn();
				$("p.caption").text($("#polaroid img:visible").attr("alt"));
			});
		}
		else{
			$("#polaroid img:visible").fadeOut(function(){
				$(this).next().fadeIn();
				$("p.caption").text($("#polaroid img:visible").attr("alt"));
			});
		}
		return false;
	});

	// Previous controls
	$("#prev").click(function(){
		if($("#polaroid img:first").is(":visible")){
			$("#polaroid img:visible").fadeOut(function(){
				$("#polaroid img:last").fadeIn();
				$("p.caption").text($("#polaroid img:visible").attr("alt"));
			});
		}
		else{
			$("#polaroid img:visible").fadeOut(function(){
				$(this).prev().fadeIn();
				$("p.caption").text($("#polaroid img:visible").attr("alt"));
			});
		}
		return false;
	});

});

What it’s “saying” is:
firstly, make sure that p.caption’s text is that of the visible image’s alt attribute.

When “next” is clicked, if the last image is visible, fade out this image and once that is done, fade in the first image and make sure that p.caption’s text is that of the visible image’s alt attribute.
Else, if this is not the case, fade out the visible image and once this is done, fade in the next image and and make sure that p.caption’s text is that of the visible image’s alt attribute.
Return false makes sure that the anchor link doesn’t act as a normal link.

The “previous” controls work the same, but in reverse.

Pretty cool, right?
I find it very simple, and the simplicity makes it very nice to work with.

I hope you enjoyed the tutorial and if you have any questions or anything to say, feel free to leave a comment.

What say you?

  1. Piet Alberts says:

    I would love to see you post a more advanced tutorial for image slider/carousels. What about having paginated buttons or thumbnail images to navigate the carousel.

    Do you think one could support SEO efforts more effectively by having text headings and snippets/exerts of content in these carousels.

    Nice post nonetheless. Keep up the good work.

    1. Jamy Golden says:

      Thanks :)
      Yeah, I’ve just started creating a more advanced content-slider plugin version with paginated buttons. The text headings will definitely help SEO.

  2. Stefan says:

    Awesome post. Maybe create a jQuery plugin of this slider for the community and add different transition effects. One can never have to many sliders in ones arsenal. Piet’s right about the SEO and usability of sliders as too many of them don’t take that in consideration.

    1. Jamy Golden says:

      I took what you said into consideration =) Say hello to PlusSlider.

  3. Matthew says:

    This is awesome…exactly what I need. I’m getting a problem where my images are getting positioned on above each other (like a column) rather than stacking on top of one another. However when I press the next / prev button everything is as it should be.

    where should this code be?

    $(document).ready(function(){
    	$("#polaroid").after('<div id="polaroid-caption"><a id="prev" href="#"></a><a id="next" href="#></a><p class="caption"></p></div>');
    });
    1. Jamy Golden says:

      Hey, I’ve changed the javascript slightly.

      What was happening was that the CSS wasn’t properly due to the images being slow to load.
      This was easily fixed by changing:

      $(document).ready(function(){

      to:

       $(window).load(function(){

      So, instead of everything loading once the DOMM was ready, it loads once everything else on the page has loaded, which fixes our problem :)

      And regarding your other question: ‘where should this code be?’
      I’ve added that to the rest of the javascript (See above) to avoid further confusion.