JavaScript Image Gallery

Making an online gallery of pictures should be a quick process. The gap between snapping some pictures and publishing them on the web ought to be a short one. Here’s a quick and easy way of making a one-page gallery that uses JavaScript to load images and their captions on the fly.

Article Continues Below

The mark-up#section2

I’ve put together some photographs that I want to make into an online gallery. The simplest way of linking to the images is to put them in a list like this:

<ul>
<li><a href="images/bananas.jpg" title="A bunch of bananas on a table">some bananas</a></li>
<li><a href="images/condiments.jpg" title="Condiments in a Chinese restaurant">two bottles</a></li>
<li><a href="images/shells.jpg" title="Seashells on a table">some shells</a></li>
</ul>

Right now, clicking on one of those links leads straight to the image. I’m going to use JavaScript to intercept that click and perform a different action instead.

The JavaScript will dynamically update a placeholder image and description, creating a slideshow effect.

I’m going to use a blank .gif for the placeholder image. I could just as easily use the first image in my gallery or some kind of “intro” image. The important thing is that the image and the description have unique IDs. I’m going to call the descriptive paragraph desc and the image placeholder.

<p id="desc">Choose an image to begin</p>
<img id="placeholder" src="images/blank.gif" alt="" />

Don’t add any height or width attributes to the placeholder image or else all the images in the gallery will be squeezed or stretched to the same size.

The JavaScript function#section3

Now it’s time to write the JavaScript. This should be placed in the <head> of the document or in an external file. I’ll call the function showPic

function showPic (whichpic)

As you can see, this function will be accepting just one parameter: whichpic. This refers to the link pointing to whichever picture I want to display.

The showPic function is going to be interacting with the desc and placeholder elements by referring directly to their IDs. The first thing I need to do is ensure that this is a capability of the browser executing the function. This is done by checking for the existence of document.getElementById:

if (document.getElementById)

Once the browser passes that test, the placeholder image can be swapped out. This is done by replacing the src value of the placeholder with the href value of the whichpic link:

document.getElementById(‘placeholder’).src = whichpic.href;

At the same time, I want to swap out the text within the desc paragraph. I could use proprietary JavaScript such as innerHTML but there’s a cross-browser solution available in the form of childNodes[0].nodeValue. This expression means the value of the first child node of an element. In our case, that will be the text inside the element.

The desc text can be replaced with the text from the whichpic link:

document.getElementById(‘desc’)»  .childNodes[0].nodeValue = whichpic.childNodes[0].nodeValue;

But it would be even better to replace the desc text with the content of the title attribute from the whichpic link:

document.getElementById(‘desc’)»  .childNodes[0].nodeValue = whichpic.title;

I needn’t decide on one arbitrarily. I can test for the existence of a title attribute. If it exists, use that text. Otherwise, use the link text:

if (whichpic.title) {
   document.getElementById('desc')»  .childNodes[0].nodeValue = whichpic.title;
} else {
   document.getElementById('desc')»  .childNodes[0].nodeValue = whichpic.childNodes[0].nodeValue;
}

Lastly, I want to make sure that the whichpic link isn’t actually followed by returning false:

return false;

Unless, that is, the browser didn’t understand document.getElementById. In that case, I do want the link to be followed so true is returned instead.

Here’s the finished function:

<script type="text/javascript" language="javascript">
function showPic (whichpic) {
 if (document.getElementById) {
  document.getElementById('placeholder')»  .src = whichpic.href;
  if (whichpic.title) {
   document.getElementById('desc')»  .childNodes[0].nodeValue = whichpic.title;
  } else {
   document.getElementById('desc')»  .childNodes[0].nodeValue = whichpic.childNodes[0].nodeValue;
  }
  return false;
 } else {
  return true;
 }
}
</script>

Calling the function#section4

All that remains is to call this function from each of the links. In order to pass a value for whichpic, each of the links could be assigned a unique ID. However, it’s much easier just to pass the value this which would mean that whichpic will have the value of “this element calling the function.”

I’ll use the onclick event handler (it would be a good idea to also use onkeypress for people navigating by keyboard). Because the showPic function determines whether the link is actually followed or not, I want the action of clicking the link to return whatever the function returns. If the function returns false, the link isn’t followed. This done by using onclick="return showPic(this)".

<ul>
<li><a  showPic(this)" href="images/bananas.jpg" title="A bunch of bananas on a table">some bananas</a></li>
<li><a  showPic(this)" href="images/condiments.jpg" title="Condiments in a Chinese restaurant">two bottles</a></li>
<li><a  showPic(this)" href="images/shells.jpg" title="Seashells on a table">some shells</a></li>
</ul>

Let’s see it in action.


function showPic (whichpic) { 
 if (document.getElementById) { 
  document.getElementById('placeholder').src = whichpic.href; 
  if (whichpic.title) { 
   document.getElementById('desc').childNodes[0].nodeValue = whichpic.title; 
  } else { 
   document.getElementById('desc').childNodes[0].nodeValue = whichpic.childNodes[0].nodeValue; 
  } 
  return false; 
 } else { 
  return true; 
 } 
}

There you have it: a simple JavaScript image gallery. It degrades gracefully so that older browsers can still follow the links and see the images. It works as expected on IE5+ and Netscape 6+ on Windows and Mac. It also works in Safari and all the various flavors of Mozilla like Firebird and Camino.

87 Reader Comments

  1. Thanks for your advice, and your patience.

    I took another look at the script on http://www.villagepreschoolcenter.com/gallerytest.html but I was unable to find a problem; that is, all the braces (“}”) are in the right place. Take a look at the page and view the script for yourself. You’ll notice that the alerts function just fine, and that the nested if statement (as well as the nested else statement) execute properly. In this page, I’ve commented out the offending lines so that the only thing running is the swapping of the picture and the alerts to track the script.

    Now, if you’ll go to http://www.villagepreschoolcenter.com/gallerytest1.html you’ll find the _same exact script_ with the exception that the lines

    document.getElementById(‘desc’).childNodes[0].nodeValue = thepic.title;

    and

    document.getElementById(‘desc’).childNodes[0].nodeValue = thepic.childNodes[0].nodeValue;

    are uncommented. Since the alerts show me where the script is executing I’ve narrowed the problem down to these two lines. In each case, the script runs just fine _until_ we get to one of these lines, when, for some reason, the browser ends up following the link and loading the improperly.

    What could be rwrong with these lines? 🙁 I’m just stumped.

    Anyway. Thanks, yet again.

  2. Your code is way too complicated. Instead of childNodes[0], use firstChild. It’s the same thing. I don’t know what’s wrong. I haven’t the time to help newbies. I’m writing my own version which is simpler than this.

  3. If you just used my DOM API you wouldn’t need the first if.
    Here it is again…
    //Powered by DCScript
    function DOMCall(name) {
    if (document.layers)
    return document.layers[name];
    else if (document.all)
    return document.all[name];
    else if (document.getElementById)
    return document.getElementById(name);
    }
    Call it like so:
    DOMCall(“object”).style.color=”blue”;
    Where “object” is the object’s id.

  4. I tried to put my money where my mouth is by writing an article about combining IE’s and the W3C’s DOMs. It produced quite useful effetcs, but here is what happened:
    ALA Editor: it works in IE? NOOOOOOOOOO!!!!!!!!!!
    So I assume that if it worked, it was too good.
    Heh.

  5. Is there a way to modify this so that there is
    A. a pop up window to see the pics in
    and
    B. a way to tell it to scroll thru a certain number of jpg’s or maybe a particular folder?
    I am thinking that if I just plug in my digital camera, I get a buttload of jpg’s named DSC101, DSC102,DSC103,etc. I would like to not have to label them and reference that label in order to put them online using this javascript.

  6. Okay, I’m gonna give this one more (final) go. This seems to be working for everybody except me, so obviously something I’m doing is flawed. That said, I’m at a total and utter loss at trying to figure it out — I’m stumped.

    I just looked over the Germ Gallery that Jon showed us. (By the way, it’s very nice. I like it, lots.) 🙂 Anyhow, I went through the js.js script you ran on that, Jon, and it is functionally identical to what I am using on this preschool’s gallery test page (at http://www.villagpreschoolgallery.com/gallerytest1.html ) and yet, the browser will always end up following the links.

    What is different? What is wrong in my gallery that’s causing this? Anyway…I don’t mean to be a pest, (advance apologies if I am) I just really want to understand what is happening.

    Thanks again.

  7. I can’t get anywhere with that link. I told you what to do. Get rid of the first if statement and replace it with the DOM API (then, no problem with braces plus it becomes more usable). I can’t help you if you won’t listen to me.

  8. Firstly, an onmouseover event should be added to the links making the status bar display something like ‘view (title)’ where title is dynamically extracted from the link’s title attribute. This will minimize confusion for visitors in a javascript-capable browser expecting a new page to load.

    Secondly, non-javascript users should be pointed to a server side version of the same page. Those that commented that this should be done solely on the server side miss the idea that this solution saves bandwidth for both you and your visitors.

  9. This photo gallery provided a quick solution for a simple business’ website. We’re finishing up a complete overhaul of our site and after fighting with complicated javascript (& dreamweaver) that this college student does not understand, this article was the light at the end of the tunnel! Now our “facilities” page will be as cool as the other guy’s 😉

  10. I had a look at your preschool image gallery code and also ran into issues. You can check out the gallery that I did at http://dasme.org/imagegal/ and copy the script code that I use. On that page the second pic has a caption that will appear when clicked.

    I am really not sure why your page breaks with the code that you have, but I can assure you that mne works. Try using my script and see if that helps. I origionally thought it may of been the doctype def that you are using on your page, but my page still properly renders and works with the base html 4.01 trans definition. I’m stumped 🙂

  11. Well Dante, you’ve shown some aspect of maturity by at least trying to be helpful towards another poster. Who would have thought such compassion would be forthcoming from someone who otherwise gives the impression of being a spiteful troll?

    It is unfortunate that you feel it necessary to jump and stick your oar in whenever knowledge is shared and sad that this web of ours allows you to do so with such unhelpful frequency. You rail against the ‘flashy script-hacking’ that goes on here. Well, I’m sorry to say it, but a lot of the sites that go on to be created by those who read and learn here are a damn sight more successful and with a far higher aesthetic value – ie: as an added bonus to looking nice, they WORK! – than your own site, which you are evidently quite proud of.

    Could it be then, that this site of which you are so proud is the same one that brings up an alert if you dare visit with Mozilla berating you for your choice of browser and steadfastly refusing to work in the way it was obviously intended? I congratulate you on your narrow and counter-productive efforts.

    Physician heal thyself.

    PS. I’m sure PPK is thrilled by your evangelical use of his moniker as a means of shoring up your arguments instead of having actual originality of thought. Do you pay him the licensing fee?

  12. An interesting bug in http://www.villagepreschoolcenter.com/gallerytest.html, which took me longer to track down than I planned!

    Your script fails when you try to assign some text to
    document.getElementById(‘desc’).childNodes[0].nodeValue

    It’s failing because that node’s a leaf: it doesn’t have any child nodes. The quick’n’dirty fix would be to change ‘

    ‘ to ‘

    some placeholder text

    ‘. Then it would have a text node as its first (and only) child.

    As an alternative (or in addition) you could add a little sanity-checking and recovery to the script itself. I am
    not a DOM scripting wizard. But something like the following should work.

    function showPic( theAnchor ) {
    // Assigns the value of theAnchor.href to document.getElementById( ‘placeholder’ ).src
    // And sets the text of document.getElementById( ‘desc’ ) theAnchor’s title or to its text content

    // Returns false on success, true on failure 😉
    // Disclaimer: tested hardly at all and only in Safari1.2

    if ( document.getElementById && theAnchor.tagName == “A” && theAnchor.href && ( theAnchor.title || ( theAnchor.firstChild ) ) ) {
    myImageElement = document.getElementById( ‘placeholder’ )
    if( myImageElement && (myImageElement.tagName == “IMG”) ) {

    myCaptionElement = document.getElementById( ‘desc’ )
    // We probably should sanity-check what kind of element we have here.
    // But there are an awful lot of valid possibilities, so
    // it’s an exercise left to the reader

    myCaptionText = theAnchor.title ? theAnchor.title : theAnchor.firstChild.nodeValue
    myImageHref = theAnchor.href

    myImageElement.src = myImageHref
    if ( myCaptionElement.firstChild ) {
    myCaptionElement.firstChild.nodeValue = myCaptionText
    } else {
    if( document.createTextNode ) {
    myCaptionElement.appendChild( document.createTextNode( myCaptionText ) )
    } else {
    // no caption set. But never mind….
    }
    }
    // image loading should have been ok so
    return false
    }

    }
    //failed so
    return true
    }

  13. I don’t know thy this is so complex.
    if (!document.getElementById)
    var r = false;
    else var r = true;
    At the end:
    return r;
    Why use all that complex if/else code when the above (or adding the DOM API) would’ve done?
    I use a browser detect (very bad desicion, but I needed to). Mozilla and all none-IE browsers totally screw up everything, so I disabled it. It will be fixed in the redesign (if I do it), but for now I punish these browsers. Yes. What a bad designer I am. Can we change the subject?

  14. I recently agreed to make a web page for my wife. I hade coded a little html in the mid-90’s when things were much simpler (and boring by today’s standards). I figured I’d better come up to speed before starting. Wouldn’t you know, of all the web design books at Border’s, I picked Zeldman’s DWWS. Lucky me.

    Imagine my frustration in trying show a LOT of images (my wife Rebecca is a lampwork glass bead artist) AND use css AND make it compliant AND make it smooth. Dang.

    Anyway, I came up with something that is akin to Mr. Keith’s idea but different. Take the code if you find it useful. http://www.rebeccas-beads.com

    Thank you Mr. Zeldman and other standards proponents.

  15. Actually it’s IE that’s screwed up. Of course it represents the majority of browsers out there, so making sure things work on it is a good thing. But being able to code once and distribute to any client is the ideal. If IE were compliant, then we wouldn’t have to come up with so many hacks just to make a site behave as we expect.

    Finally, if your site is any indication, then yes you are a very bad designer. But then you don’t care about that anyway do you Dante?

  16. Hi, this may be really simple, but I was wondering if it’s possible to either make the image or caption a link? If so, an example would be greatly appreciated!

  17. Frankly I don’t care about people calling my design bad anymore. People like you don’t visit my site, anyway. My site was aimed at people looking for info on San Francisco History, which flowed smoothly. Maybe that failed, but I’m fixing it. So go ahead and sue me for trying to help people.

  18. Ian, just wanted to express my (belated but still very) sincere thanks to you for figuring out what was wrong with my script there.

    Your suggestions worked perfectly, and they taught me a _lot_ of valuable stuff about JavaScript and the DOM. Thanks many bunches.

  19. Awesome script! Just what I’ve been looking for.

    I’ve been trying to figure out where I can add a bookmark tag somewhere on this script, so whenever I click on an image it will display and also make a call to the bookmark on the page.

    Thanks first.

  20. I think this is a great little script. I was just wondering if it would be difficult to make the image that javascript intercepts a link to a larger image. So, when I click on the text link it shows the preview, and then when the preview is clicked (the link that javascript intercepts) it opens a larger version of that image in a new window.

    thanks

  21. I applied the techniques in this article to an existing page, and I must have some simple puncuation in the code wrong (even though I cut and pasted most of it)

    Does anyone have a working sample of these gallery using image thumbnails? I may be able to get mine working by looking at someone else’s.

  22. Is it possibile to link the target image to a larger version of the image?
    Thanks

  23. Paul: I successfully executed using thumbnails on this site: http://summerinnbnb.com/haines.php

    An interesting note about the caption area… I found that if your placeholder text is say two lines long, and you replace it with a caption that’s 3 lines long you may run into issues with some browsers (Safari being one of them, didn’t test beyond that). The issue I ran into was that the third line gets cut off when you click on an image with a 3 line caption. I kinda had to hack to fix it – by forcing my placeholder text to be extra large, adding a few br’s and a non-breaking space.

  24. Great article, thanks again ALA. I did find a problem in Safari though. If your images are not exactly the same size they will be stretched, matching the size of the largest image (I tried it with images of same height different widths, but assume the reverse is also true). I did not specify height or width in code (exactly the same as in the article) & it works fine in IE5.5 Win, Win/Mac Firbird/Firefox, and Camino. I did not change the javascript at all, just copy and paste from the article. I am running Panther 10.3.3, Safari 1.2.1.

  25. This may be a fairly basic problem for those with more experience, but being new to JavaScripting….

    What I would like is to have the caption provided not by the Title element, but instead along the lines of a PHP include?

    I guess pseudo-code for this would look something like this…

    01

    …where I assume myCaption would be a text string passed to a function within the JavaScript that would then display the contents of the file 01.txt.

    Is this sort of thing possible? Either code and/or pointers to resources/examples would be appreciated.

    Thanks for taking the time to write this article. Its been quite helpful.

    Brooks

  26. Hey Jeremy, thanks for that – _very_ useful – and I even substituted thumnails for the text and it looks neat, but I found a problem….

    You say it works for IE 5+ (PC and Mac), but my version of IE (Mac 5.2.3) opens the larger images like they were a link to another page which means I lose all my lovely page formatting _and_ I’m forced to use the back button.

    Any suggestions why it would do that?

  27. Love this script and would like to use it. It’s not working for me in Netscape 7.1, and I just went through all the comments here. None of the examples work in NS7.1 (except for Rebecca’s beads – absolutely beautiful, by the way!) Works fine in IE6 and Moz.

    Here’s my attempt:
    http://garfieldz.com/chgo2004-alagallerytest.html

    Here’s a screenshot. I want it to look like it does in IE:
    http://garfieldz.com/chgo2004-alagallery-screenshot.html

    Would appreciate some help! Thanks!

  28. My bad! There was a problem with my NS profile. AOK now. Love the script! Thanks!

  29. I also love this image gallery. I really need these previous / next buttons though. I thought maybe this can be accomplished using a bit of javascript and using display:none? Or changing the Z-index using javascript? Does anybody know how to do that?

  30. Please only use the following browsers in your comparisons.

    IE 6.1 (fully patched)
    Opera 7.5b/7.23
    Mozilla 1.7b
    Firefox 0.8
    Safari (1.2)

    In case you didn’t know IE 3,4,5, Netscape 4,4.6,4.08,6 are obsolete so let’s not say i hope it can work in any of them.

    Are we ever going to move forward. I might as well bring out my betamax video machine so i can watch the latest Matrix dvd disc on it, watch me start crying when i can’t insert the disc.

Got something to say?

We have turned off comments, but you can see what folks had to say before we did so.

More from ALA

I am a creative.

A List Apart founder and web design OG Zeldman ponders the moments of inspiration, the hours of plodding, and the ultimate mystery at the heart of a creative career.
Career