Shadowbox image gallery with thumbnails
Shadowbox is an amazing tool javascript popup replacemant for many different types of content. We all have seen many of the same tools and you probably have already spotted shadowbox as well. If you have not, be sure yo check it out since it is insanely simple to include in your site.
In this tutorial/showcase I show you how to add a filmstrip thumbnailpreview as in the following example:
Although shadowbox does have an image gallery and even has slideshow functionality build in it doesn’t have the option to show thumbnails of the images in your gallery when shadowbox is open. Luckely, shadowbox is super easy to edit as well.
So I created this functionality myself. Well, I must be honest, credit goes to Peter Mitchell for posting a solution based on shadowbox v.3b but it didn’t fit my needs completely. First of all it didn’t look to my taste, secondly I wanted it to work with shadowbox v3.rc1 which is the current version and thirdly, some things were missing, like, what happens if we don’t have a thumbnail for a link. Lets get into the code!
First we need to make some changes to the code and later we need to adapt the css as well. Important note is that we will not break any of the existing functionality although the skin looks different and is optimized for thumbnail view. For each change I made I will show the before and after. In order for a thumbnail to show the link must be an image. The source for that image will be used for the thumbnail. If the link is not an image, the basic shadowbox counter will be showed. All the javascript that gets edited is done in shadowbox.js and all the css is done in shadowbox.css.
First we need to add the thumnail source info to the gallery elements.
-
buildCacheObj: function(link, opts){
-
var obj = {
-
link: link,
-
title: link.getAttribute(‘title’),
-
options: apply({}, opts || {}),
-
content: link.href // don’t use getAttribute here
-
};
becomes:
-
buildCacheObj: function(link, opts){
-
var obj = {
-
link: link,
-
title: link.getAttribute(‘title’),
-
options: apply({}, opts || {}),
-
content: link.href, // don’t use getAttribute here
-
thumb: link.firstChild && link.firstChild.src ? link.firstChild.src : null
-
};
Next, we need to change the function that builds the counter
-
var counter = ”;
-
if(S.options.displayCounter && S.gallery.length > 1){
-
var len = S.gallery.length;
-
-
if(S.options.counterType == ’skip’){
-
// limit the counter?
-
var i = 0,
-
end = len,
-
limit = parseInt(S.options.counterLimit) || 0;
-
-
if(limit < len && limit > 2){ // support large galleries
-
var h = Math.floor(limit / 2);
-
i = S.current – h;
-
if(i < 0) i += len;
-
end = S.current + (limit – h);
-
if(end > len) end -= len;
-
}
-
while(i != end){
-
if(i == len) i = 0;
-
counter += ‘<a onclick="Shadowbox.change(‘ + i + ‘);"’
-
if(i == S.current) counter += ”;
-
counter += ‘>’ + (i++) + ‘</a>’;
-
}
-
}else
-
var counter = (S.current + 1) + ‘ ‘ + S.lang.of + ‘ ‘ + len;
-
}
becomes:
-
var counter = ”;
-
if(S.options.displayCounter && S.gallery.length > 1){
-
var len = S.gallery.length;
-
-
if(S.options.counterType == ’skip’ || S.options.counterType == ‘thumbskip’){
-
// limit the counter?
-
var i = 0,
-
end = len,
-
limit = parseInt(S.options.counterLimit) || 0;
-
-
if(limit < len && limit > 2){ // support large galleries
-
var h = Math.floor(limit / 2);
-
i = S.current – h;
-
if(i < 0) i += len;
-
end = S.current + (limit – h);
-
if(end > len) end -= len;
-
}
-
while(i != end){
-
if(i == len) i = 0;
-
if(S.options.counterType == ‘thumbskip’ && S.gallery[i].thumb) {
-
//thumbskip
-
counter += ‘<a onclick="Shadowbox.change(‘ + i + ‘);"’;
-
if(i == S.current) counter += ”;
-
counter += ‘>’ + ‘<img src="’ + S.gallery[i].thumb + ‘" />’ + ‘</a>’;
-
i++;
-
}
-
else { //skip
-
counter += ‘<a onclick="Shadowbox.change(‘ + i + ‘);"’;
-
if(i == S.current) counter += ”;
-
counter += ‘>’ + (i++) + ‘</a>’;
-
}
-
}
-
}else
-
var counter = (S.current + 1) + ‘ ‘ + S.lang.of + ‘ ‘ + len;
-
}
The last step is to edit the html and the css so that the filmstrip will be displayed correctly. I will show you what I did to create mine but I encourage you to create your own look (and feel) to make it fit your needs.
-
markup: ‘<div id="sb-container">’ +
-
‘<div id="sb-overlay"></div>’ +
-
‘<div id="sb-wrapper">’ +
-
‘<div id="sb-title">’ +
-
‘<div id="sb-title-inner"></div>’ +
-
‘</div>’ +
-
‘<div id="sb-body">’ +
-
‘<div id="sb-body-inner"></div>’ +
-
‘<div id="sb-loading">’ +
-
‘<a onclick="Shadowbox.close()">{cancel}</a>’ +
-
‘</div>’ +
-
‘</div>’ +
-
‘</div>’ +
-
‘<div id="sb-info">’ +
-
‘<div id="sb-info-inner">’ +
-
‘<div id="sb-counter"></div>’ +
-
‘<div id="sb-nav">’ +
-
‘<a id="sb-nav-close" title="{close}" onclick="Shadowbox.close()"></a>’ +
-
‘<a id="sb-nav-next" title="{next}" onclick="Shadowbox.next()"></a>’ +
-
‘<a id="sb-nav-play" title="{play}" onclick="Shadowbox.play()"></a>’ +
-
‘<a id="sb-nav-pause" title="{pause}" onclick="Shadowbox.pause()"></a>’ +
-
‘<a id="sb-nav-previous" title="{previous}" onclick="Shadowbox.previous()"></a>’ +
-
‘</div>’ +
-
‘<div style="clear:both"></div>’ +
-
‘</div>’ +
-
‘</div>’ +
-
‘</div>’,
becomes:
-
markup: ‘<div id="sb-container">’ +
-
‘<div id="sb-overlay"></div>’ +
-
‘<div id="sb-wrapper">’ +
-
‘<div id="sb-title">’ +
-
‘<div id="sb-title-inner"></div>’ +
-
‘</div>’ +
-
‘<div id="sb-body">’ +
-
‘<div id="sb-body-inner"></div>’ +
-
‘<div id="sb-loading">’ +
-
‘<a onclick="Shadowbox.close()">{cancel}</a>’ +
-
‘</div>’ +
-
‘</div>’ +
-
‘<div id="sb-info">’ +
-
‘<div id="sb-info-inner">’ +
-
‘<div id="sb-counter"></div>’ +
-
‘<div id="sb-nav">’ +
-
‘<a id="sb-nav-close" title="{close}" onclick="Shadowbox.close()"></a>’ +
-
‘<a id="sb-nav-next" title="{next}" onclick="Shadowbox.next()"></a>’ +
-
‘<a id="sb-nav-play" title="{play}" onclick="Shadowbox.play()"></a>’ +
-
‘<a id="sb-nav-pause" title="{pause}" onclick="Shadowbox.pause()"></a>’ +
-
‘<a id="sb-nav-previous" title="{previous}" onclick="Shadowbox.previous()"></a>’ +
-
‘</div>’ +
-
‘<div style="clear:both"></div>’ +
-
‘</div>’ +
-
‘</div>’ +
-
‘</div>’ +
-
‘</div>’,
Last but not least, the css.
-
#sb-info, #sb-info-inner {
-
height: 20px;
-
}
-
#sb-info-inner {
-
font-size: 12px;
-
color: #fff;
-
}
becomes:
-
#sb-info, #sb-info-inner {
-
position: absolute;
-
margin: 0; /* these must have no vertical margin or padding */
-
padding: 0;
-
left: 0px;
-
bottom: 0px;
-
overflow: hidden;
-
width: 100%;
-
}
-
#sb-info-inner {
-
position: relative;
-
height: 100px;
-
font-size: 12px;
-
color: #fff;
-
}
Wait, there’s more!
-
#sb-nav {
-
float: right;
-
height: 16px;
-
padding: 2px 0;
-
width: 45%;
-
}
-
#sb-nav a {
-
display: block;
-
float: right;
-
height: 16px;
-
width: 16px;
-
margin-left: 3px;
-
cursor: pointer;
-
}
-
#sb-nav-close {
-
background-image: url(resources/close.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-next {
-
background-image: url(resources/next.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-previous {
-
background-image: url(resources/previous.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-play {
-
background-image: url(resources/play.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-pause {
-
background-image: url(resources/pause.png);
-
background-repeat: no-repeat;
-
}
becomes:
-
#sb-nav {
-
position: absolute;
-
top: 0px;
-
right: 0px;
-
height: 48px;
-
padding: 4px 24px 4px 4px;
-
width: 200px;
-
}
-
#sb-nav a {
-
display: block;
-
float: right;
-
height: 48px;
-
width: 48px;
-
margin: 16px 0 0 0;
-
cursor: pointer;
-
text-decoration: none;
-
}
-
#sb-nav-close {
-
background-image: url(resources/custom/close.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-next {
-
background-image: url(resources/custom/next.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-previous {
-
background-image: url(resources/custom/previous.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-play {
-
background-image: url(resources/custom/play.png);
-
background-repeat: no-repeat;
-
}
-
#sb-nav-pause {
-
background-image: url(resources/custom/pause.png);
-
background-repeat: no-repeat;
-
}
And, one more.
-
sb-counter {
-
float: left;
-
padding: 2px 0;
-
width: 45%;
-
}
-
#sb-counter a {
-
padding: 0 4px 0 0;
-
text-decoration: none;
-
cursor: pointer;
-
color: #fff;
-
}
-
#sb-counter a.sb-counter-current {
-
text-decoration: underline;
-
}
becomes:
-
#sb-counter {
-
margin: 4px 230px 24px 50px;
-
}
-
#sb-counter:after {
-
content: ".";
-
display: block;
-
height: 0;
-
visibility:hidden;
-
clear: both;
-
}
-
#sb-counter a {
-
text-decoration: none;
-
margin: 0px 6px 20px 0px;
-
cursor: pointer;
-
color: #fff;
-
display: block;
-
float: left;
-
}
-
#sb-counter a:hover {
-
color: #0f0;
-
}
-
#sb-counter a.sb-counter-current, #sb-counter a.sb-counter-current:hover {
-
text-decoration: underline;
-
cursor: default;
-
color: #fff;
-
}
-
#sb-counter a img {
-
border: solid 1px #000;
-
height: 85px;
-
}
-
#sb-counter a:hover img {
-
border: 1px solid #0f0;
-
}
-
#sb-counter a.sb-counter-current img, #sb-counter a.sb-counter-current:hover img {
-
border: 1px solid #fff;
-
}
We’re almost done. The last thing we have to do is set the right options in our shadowbox setup. I’ll show an example how to set shadowbox to use our functionality in the init() function.
-
Shadowbox.init({
-
slideshowDelay: 3, //set this to use slideshow
-
counterType: "thumbskip", //use our new functionality!
-
counterLimit: 10 //how many thumbnails can be shown
-
});
Unfortunately it is not permitted to redistribute shadowbox. I do have the images for the buttons that I used for you. Place them in a folder called ‘custom’ under ’shadowbox/resources/’ if you want to use them with the css I made. For the original files go to http://shadowbox-js.com/download.html and download version 3.rc1. If you want to edit the code like I did it is best to download both the build and the source version, edit the sources, compress them yourself and use the rest of the build files.
So, this is about it. I am really looking forward to your feedback and any bugs you might find. Some css related things like image hovers will not work in older versions of internet explorer, but it will not really break functionality. Also, since this is the first full-blown I wrote for SeeDoubleYou.nl I really like to get feedback on how it is written. Is everything clear enough, is there to much blabbering or is it the best tutorial you have ever read, please let me know.
files:
sb_custom_images
- Javascript
- Tutorial






18 Responses
Hi thanks for the tutorial, unfortunately the code always seems to have changed by the time i go to download the source and edit it…
I applaud your efforts though as i think that thumbnails are a no brainer for shadowbox. I’m not sure why they don’t add the functionality…
I did notice that if you resize the window that the main image grows to fill the window, thus appearing behind the thumbnails instead of above.
GL with the blog!
Yes, I’ve noticed the differences in the new version. I will write a follow-up on how to fix that. When that time comes I will look in to the resizing part as well.
Also, thanks for writing the first, non-spam response on the blog!
Great to hear!
Is there a way to copy your code without it including the number bullets?
What I’m trying to accomplish is setting the thumbs at the bottom so that they are forced to be displayed at a certain width regardless of how tall the image/browser is. I also want to keep that bar centered instead of to the edges.
Thanks
I select the text with the mouse is doesn’t take the numbers. I am looking for a better code highlighter with better selecting capabilities. I’m not really getting what your plan is with the width. The width is fixed at the moment, could you explain further. The centered option would be nice but not that trivial. If you find a nice solution though please let me know.
Hey,
Ya if i copy a couple lines it looks like the numbers aren’t there but once you paste it they show up.
Your sb-info div doesn’t have a set width, so the thumbs stick to the left and the nav sticks to the right. You can see it if you re-size the browser horizontally.
Personally i’d like them to bunch together and center below the image instead of having a space between the thumbs and nav. However what you have is better than the last solution. Having the thumbs only display as wide as the image above was getting them chopped off, which was my main problem.
I’m not really a js guy, but i can see where the css is organized in the file and when i get a chance i’ll try fooling around with the code.
Thanks for your work!
Once I get more time on my hands I will look further into this but for now you could start out by trying the following:
edit shadowbox.css by removing the margin on ‘#sb-counter’. Also remove the float and the display on ‘#sb-counter a’. Then add a ‘text-align: center’ to #sb-info.
I have only tested this the dirty way by editing with firebug. So don’t take this as a fool proof solution. You might want to check for example what happens if there are a lot more thumbnails to be displayed.
This tutorial is the type of gallery layout I want for my portfolio, but I’m clueless with css and even more lost when it comes to javascript. I’m using dreamweaver to code my gallery. Is there any way you can make a more detailed tutorial of this so even I can understand it? Keep up the good work!
Hey Andy, I’m glad you liked it. Since this tutorial doesn’t work for the newest version of shadowbox I’m considering whether I should rewrite this to work with the latest version or that I should think of a more robust solution that will keep working across newer versions. At the moment I’m still kinda busy (hence the low density in new posts) because I am working another tool to do linkbuilding (expect an article about that in a few weeks), but I hope that somewhere in the next two weeks I manage get some time to work on this. Any ideas will be much appreciated!
Hi,
Always nice to see all the efforts to share you work with people, I must admit I was expecting a lot from your code but unfortunately as you said yourself, the original code a changed . did you give some thoughts about updating yours or did you abandon the idea ?
I was thinking on rewriting the whole thing to work with the newer version of shadowbox, but then I realized that this will keep happening until shadowbox offers a solid plugin feature. So currently I am searching for other solutions. Maybe another another viewer, I don’t know. I would be very happy to hear some thoughts about it though.
Hey I’m Back!
I just stumbled upon GalleryView ( http://spaceforaname.com/galleryview )
Check out some of the demo galleries here:
http://spaceforaname.com/gallery-light.html
http://spaceforaname.com/gallery-dark.html
As you can see from the documentation it’s just a matter of changing some options to achieve either one of those demos.
Some very nice features implemented.
His original site looks like it had some difficulties with his blog but he does seem dedicated to keeping the GalleryView project active.
What do you think of it?
Hmm Gallerific also looks interesting:
http://www.twospy.com/galleriffic/
The only thing these 2 are lacking is the full screen pop up, but i think with some clever coding you could use shadowbox to launch ontop of these galleries.
Hi seedoubleyou,
I just love what you did to the original shadowbox. Looking for a framework for a private picture gallery I stumbled across your above samples – cute.
Could you give me a hint on the files required to reproduce your mod? So far I’m aware of the below one – but sure I’m missing something important..
shadowbox-base.js
shadowbox-en.js
shadowbox-img.js
shadowbox.css
shadowbox.js
sizzle.js
style.css
swfobject.js
Hey Alex. To reproduce the mod you need an older version of shadowbox, not sure where you can’t find them. I was planning on writing a plugin for the newer version of shadowbox, but until there’s no good documentation on that I keep this old version. There are some other gallery-script out there that might help you out though. I think that galleria Might be a good start. You could also look at some of the links in the above posts and here are some very nice jquery plugins, which are generally more easy to set-up (when you are used to using jquery). sites like this and that might help.
moet controleren:)
Very nice post, I surely love this site, keep it up.
any plans on an updated version of this mod? v3.03 has been out a while now and is nice and stable .. i tried my hand at an update myself, but cant seem to get it all going ( a lot of var names have been changed and im probably missing on in the translation .. that and the fact that im a novice at JS ). im sure others would agree that we’d love to see you update your code to work with the latest Shadowbox version.
I will release a new version of this site in a short while. From Then on I will update more frequently. I will definitely write a new post on this. I don’t think it will use shadowbox, but it will do the same. Anyway, check back in a few weeks.