How to make a image gallery with thumbnails

Web programming topics
Post Reply
User avatar
Saman
Lieutenant Colonel
Lieutenant Colonel
Posts: 828
Joined: Fri Jul 31, 2009 10:32 pm
Location: Mount Lavinia

How to make a image gallery with thumbnails

Post by Saman » Sun Mar 07, 2010 5:50 am

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. So here is another one.

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)
demo.JPG
demo.JPG (80.09 KiB) Viewed 3023 times
The idea is to let a simple javascript grab each <img> element in the list and place it as a background in the parent <li> 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 <li> object that toggles it’s child’s <img> element’s visibility and adds an “active” class name to the <li>. Using CSS, we can then place the <img> 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:

Code: Select all

<ul id="gallery">
<li><img src="images/je_1.jpg" alt="Josef & Erika 1"></li>
<li><img src="images/roland_ads_2.jpg" alt="Roland Ads"></li>
<li><img src="images/cd_2.jpg" alt="CD Cover 2"></li>
<li><img src="images/cd_1.jpg" alt="CD Cover 1"></li>
<li><img src="images/je_3.jpg" alt="Josef & Erika 3"></li>
<li><img src="images/je_2.jpg" alt="Josef & Erika 2"></li>
<li><img src="images/lktrd_poster1.jpg" alt="LKTRD Poster"></li>
<li><img src="images/je_4.jpg" alt="Josef & Erika 4"></li>
<li><img src="images/inside_1.jpg" alt="Inside Magazine"></li>
<li><img src="images/oceanen_4.jpg" alt="Oceanen"></li>
</ul> 
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:

Code: Select all

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.length; i++) {
                        li[i].style.backgroundImage = 'url(' + li[i].getElementsByTagName('img')[0].src + ')';
                        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.length; 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 <ul> 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:

Code: Select all

/* general styling for 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:

Code: Select all

/* styling without javascript */
#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:

Code: Select all

<!--[if lt IE 8]>
<style media="screen,projection" type="text/css">
#jgal li { filter: alpha(opacity=50); }
#jgal li.active, #jgal li:hover { filter: alpha(opacity=100); }
</style>
<![endif]--> 
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 document.write before the script to hide the #gallery item:

Code: Select all

<script type="text/javascript">document.write("<style type='text/css'> #gallery { display: none; } </style>");</script>
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:

Code: Select all

<!--[if lt IE 6]><style media="screen,projection" type="text/css">#gallery { display: block; }</style><![endif]-->     
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:

Code: Select all

img { width: 80px; height: auto; } 
So, in theory, you could clone the <img> object using javascript, add a image scaling CSS rule and make it clickable in the same way as I did with the <li> 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.
Post Reply

Return to “Web programming”