Lightweight Thumbnails Image Gallery

Showing images online is a big thing. Besides elementary stuff like flickr, there are a vast number of image gallery scripts available online. Some are free and some cost a little. Some are really good and some are terrible. Some of the biggest flaws with the existing ones are that they either require flash, server-side scripting or a heavy javascript source. And the ones that uses pure javascript are rarely degradable and don’t include thumbnails.

 

This is what I wanted for this gallery:

  • No server-side scripting
  • Super-fast browsing without fades
  • Dead-simple HTML with a list of images
  • Lightweight, unobtrusive javascript to create thumbnails
  • CSS styling to create different layouts
  • Degradable if javascript or images are disabled
  • Cross-browser consistency (sort of)

The idea is to let a simple javascript grab each element in the list and place it as a background in the parent

  • element. Then let CSS style the thumbnails as small blocks with a defined height/width, a background-position and some other visual stuff. After that, we add a click-event for each
  • object that toggles it’s child’s element’s visibility and adds an “active” class name to the
  • . Using CSS, we can then place the absolutely to make it appear at the same position for each thumb. As a bonus, let’s put the alt value as title so we can have a glimpse of what’s coming when hovering the thumbnail. Ok.

    The HTML

    The HTML should be really simple. I used some portfolio images for this example:

    This will simply display a list of all your images. Now let’s add the magic.

    The Javascript

    Here is the simple javascript I composed. I have not used jquery or any other framework, just plain simple object literation that parses the gallery object, switches it’s id and does all the other stuff I described above:

    var gal = {
    init : function() {
    if (!document.getElementById || !document.createElement || !document.appendChild) return false;
    if (document.getElementById('gallery')) document.getElementById('gallery').id = 'jgal';
    var li = document.getElementById('jgal').getElementsByTagName('li');
    li[0].className = 'active';
    for (i=0; i li[i].style.backgroundImage = 'url(' + li[i].getElementsByTagName('img')[0].src + ')';
    li[i].style.backgroundRepeat = 'no-repeat';
    li[i].title = li[i].getElementsByTagName('img')[0].alt;
    gal.addEvent(li[i],'click',function() {
    var im = document.getElementById('jgal').getElementsByTagName('li');
    for (j=0; j im[j].className = '';
    }
    this.className = 'active';
    });
    }
    },
    addEvent : function(obj, type, fn) {
    if (obj.addEventListener) {
    obj.addEventListener(type, fn, false);
    }
    else if (obj.attachEvent) {
    obj["e"+type+fn] = fn;
    obj[type+fn] = function() { obj["e"+type+fn]( window.event ); }
    obj.attachEvent("on"+type, obj[type+fn]);
    }
    }
    }

    gal.addEvent(window,'load', function() {
    gal.init();
    });

    The CSS

    The CSS is not very complicated either. Since we switched the gallery

      id from “gallery” to “jgal”, we can define different styles depending on whether the user has javascript enabled or not. The javascript also adds a class “active” to the active thumbnail li object, wich allows us to style it properly. In this case I chose to create 80px * 80px thumbnails in two columns and the large image to the right of the thumbnails. I also added some hover and active effects in this example:

      * { margin: 0; padding: 0; }
      body { padding: 20px; }

      /* begin gallery styling */
      #jgal { list-style: none; width: 200px; }
      #jgal li { opacity: .5; float: left; display: block; width: 60px; height: 60px; background-position: 50% 50%; cursor: pointer; border: 3px solid #fff; outline: 1px solid #ddd; margin-right: 14px; margin-bottom: 14px; }
      #jgal li img { position: absolute; top: 20px; left: 220px; display: none; }
      #jgal li.active img { display: block; }
      #jgal li.active, #jgal li:hover { outline-color: #bbb; opacity: .99 /* safari bug */ }

      Now let’s add some basic styling if javascript is disabled:

      #gallery { list-style: none; display: block; }
      #gallery li { float: left; margin: 0 10px 10px 0; }

      IE 5-7 doesn’t understand the CSS 3 property opacity. So let’s add a fix for them that uses the microsoft-exclusive filter property:

      #jgal li { filter: alpha(opacity=50); }
      #jgal li.active, #jgal li:hover { filter: alpha(opacity=100); }

      The :hover effect above will only apply to IE7, since IE6 can’t use the :hover pseudo-class on other elements than anchors.

      One more fix

      There is one last problem with this script; It doesn’t execute until the images are loaded, causing an ugly flicker. The fix is to use an ugly [removed] before the script to hide the #gallery item:

      [removed](" #gallery { display: none; } ");

      This works fine, except that explorer versions below 6 will not execute the gallery javascript. So we need to show the #gallery again for those browsers:

      #gallery { display: block; }

      You might also want to add a loading animation or text using the same technique if your images are heavy, since nothing will be shown until all images are loaded.

      I tested this gallery in all my browsers with the following results:

      • IE5/win, IE5.5/win, IE5/mac: no javascript applied, resorted to default #gallery styling
      • IE6/win: OK, but no hover and no outline
      • IE7/win: OK, but no outline
      • Firefox/win: OK
      • Firefox/mac: OK
      • Safari2/mac: OK
      • Opera8/win, Opera9/win: OK, no opacity

      Enjoy!

      Update: Some people have asked if it’s possible to show a resized version of the image as thumbnail instead of a cropped version. You can do it in two ways, either use the CSS3 property background-size and sit back and wait for browser implementation (only Safari 3 and konqueror supports it as of today). Or, you can alter the javascript and CSS a bit. CSS supports dynamic image scaling, so by setting a width to, say, 80px and height to auto you can scale down an image with constrained proportions, f.ex:

      img { width: 80px; height: auto; }

      So, in theory, you could clone the object using javascript, add a image scaling CSS rule and make it clickable in the same way as I did with the

    • object. Personally, I prefer not scaling the image though, since browsers are generally very bad at it.

      Some people have claimed that it won’t “work” without javascript. Well, it won’t be clickable with thumbnails in the same way, no, but the images are still there for viewing. And, you can add custom CSS for the gallery if javascript is disabled. So that’s not entirely true.

      Download: http://www.htmldrive.net/items/download/697

  • Leave a comment