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 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>
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 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 */ }
Code: Select all
/* styling without javascript */
#gallery { list-style: none; display: block; }
#gallery li { float: left; margin: 0 10px 10px 0; }
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]-->
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>
Code: Select all
<!--[if lt IE 6]><style media="screen,projection" type="text/css">#gallery { display: block; }</style><![endif]-->
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
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; }
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.