FancyZoom Meet Prototype
I hate lightboxes. Everyone who knows me, knows this. When I saw Cabel Sasser’s FancyZoom, a similar interaction, I liked the idea but not the exact implementation, so I rewrote it.
So what didn’t I like about Cabel’s? Nothing big and nothing deal breaking, just more a matter of preference. First, I didn’t like that it used AJAX. I tend to lean towards the side of rendering everything and then showing and hiding, rather than loading stuff with AJAX. I’m not a fan of waiting once a page is loaded, so my version works with any HTML already included on the page.
Second, Cabel, being the rebel that he is, built his from scratch with no use of any JavaScript libraries. That is cool and all, but I almost always have Prototype and Scriptaculous included. Cabel’s version without Prototype is two scripts that weigh in at 36k. My version with prototype is only 12k. Granted, we are doing things a bit differently, and mine has the overhead of Prototype and Scriptaculous, but like I said, I’d have that overhead with or without the fancy zoom.
Third, Cabel’s implementation only works for images and it loads them via AJAX (to save initial page weight). I think that the zoom interaction is pretty interesting so I didn’t want a version limited to just images. Mine supports pretty much any html you can throw in a div (images, text, flash, etc.). The only caveat is the html must be on the page somewhere, at this point.
Fourth, and final, is that I liked Apple’s rounded corners, as opposed to the original fancy zoom’s square edges. Sexy. You can see it on Apple’s site (click on the watch video button) or just take a gander at the screenshot below.

Demos
As always, I’ve whipped together a little demo site for you.
A Few Snippets
I won’t go into all the code, as it would take forever, but I’ll mention a couple of snippets from fancy zoom.
Object.extend(String.prototype, {
// if a string doesn't end with str it appends it
ensureEndsWith: function(str) {
return this.endsWith(str) ? this : this + str;
},
// makes sure that string ends with px (for setting widths and heights)
px: function() {
return this.ensureEndsWith('px');
}
});
Object.extend(Number.prototype, {
// makes sure that number ends with px (for setting widths and heights)
px: function() {
return this.toString().px();
}
});
When you are setting widths and height in prototype you always have to have ‘px’ on the end. I got tired of adding it, so using the snippets above I can do things like the code below, and I’m guaranteed to always end up with the correct unit.
180.px() // => '180px'
'180'.px() // => '180px'
'180px'.px() // => '180px'
Also, for the first time I used Effect.Parallel, which allows you to run multiple effects at once really easily. In this case, I’m running Effect.Appear, Effect.Move and Effect.Morph in sync to make the transition feel like it is jumping off the page.
At any rate, this was an interesting project and I’m sure I’ll be updating it with more goodies as I use it. The code and examples are up on Github so feel free to fork and give back. Hope it comes in handy for you.
Post and Author Info.
Published September 02, 2008 by:
Commenting is currently off for this post.
So far there are 38 comments.

Nice work John! Very clean implementation.
September 2nd, 2008
Excellent script! I really like the solid and clean effect this gives – there has always been something about other ‘modal window’ solutions that makes them look flimsy. Are you going to force me to use Prototype, or is someone going to come up with a jQuery version? I’d do it myself, but it wouldn’t be for a while.
Keep up the good work! :)
September 2nd, 2008
I wouldn’t expect support for Google Chrome, especially with it just being released today… but noticed that none of the links after the first image link work in it. I ran the demo in Safari 4/Win and it worked as intended. (I’m assuming it has to do with Chrome’s V8 Javascript engine…)
Other than that issue… this looks great. Can’t wait to play around with it.
September 2nd, 2008
I saw this on GitHub this morning and that 2nd screenshot sold me. I needed this last night and it came out today. :D Awesome stuff John, as always. :)
September 2nd, 2008
@Chris – Weird, I haven’t downloaded it yet. I’ll have to try it out.
@Bryan – Ha. Sweet. Glad I could help out. Sorry I was a day late. :)
September 2nd, 2008
Nice work John. But really, a table for the box? Is that just to make the box dropshadow stretch easier?
Hmmm… might have to fork it and play around.
September 2nd, 2008
Very cool. I tend toward jQuery myself, but I may step over to Prototype this week to play with this one. Great implementation; I like that it will “zoom” in on text as well as images.
Thanks!
September 2nd, 2008
Simply beautiful. Progressive enhancement to boot!
September 2nd, 2008
I was planning to convert a FancyZoom effect into Mootools (my preferred library), but cool to see it in Prototype, which I use at my day job.
One thing I noticed that you dropped in the version, is the actual Zoom effect of the image. That’s my favorite part of the library. Currently, the box opens from the image, but displays the image only after the box becomes full size.
FancyZoom has the actual image zoom.
September 2nd, 2008
@Stickel – Yep, a table. I’m sorry it hurt you. :) I looked around at several projects and they all used a table like that. I’m not opposed to doing it another way but that is the easiest way to do the rounded, alpha-transparent corners. If it were square, a few wrapping divs would be easy.
@Sean – Yeah, that wouldn’t be too hard to implement for images but scaling all the content was jacking things up. I’ll fix it sometime but ran out of steam. :)
@jQueryists – You never know whether or not another member of Ordered List is working on a jQuery version. Muhahaha.
September 2nd, 2008
Hi John,
Great job with the mod on Fancy Zoom!
One question, is there any way to put a scroll bar into FancyZoom, so it if the HTML content is bigger than the FancyZoom window it brings up a scroll bar?
I have placed style=”overflow:auto;” in the zoom_content div in the js file but it didn’t work.
I even placed it in the zoom div in the js file but the scroll bar appears outside the fancy zoom box.
Any help would be appreciated.
Cheerio,
S
September 2nd, 2008
S. I haven’t looked at it but you could probably put another div, inside the zoom div (aka, the content that gets shown in the fancy zoom) and give that overflow: auto; to give you the scroll bars. That should work, at least in my head. :)
September 2nd, 2008
FancyZoom is the Hansel of LightBoxes
- so hot right now -nice to see it ported to Prototype and hinted for jQuery. The interaction I hate (for usually being botched) is closing. Clicking on or outside the expanded content should always collapse the box.FancyZoom gets half points, but this conversion does neither. Honestly, I don’t know if that’s an easy or hard fix, but it’s the LightBox Grail in my view.
September 3rd, 2008
Nice work, but for me, the image-zooming-feature really needs to be implemented before i would actually use it in one of my sites. This simply is the best thing about the fancyzoom in my opinion and without that, I still prefer lightbox.
September 3rd, 2008
@Mic: Thanks, tried it but to no avail….
S.
September 3rd, 2008
My apologies i meant
@Mike
September 3rd, 2008
FancyBox is what I use, a jQuery plugin which works really well.
September 3rd, 2008
Awesome work John – I was actually just wondering why nobody hadn’t thought of doing this and then bam, you did it.
I have to agree with Brendan though. I love the convenience of closing FancyZoom by clicking on the image instead of the (x) button.
September 3rd, 2008
It’s a nice effort but the usability is much less desirable than a lot of other lightboxes and modals out there. Having to click the cross requires a great amount of precision and time, as opposed to clicking outside or clicking the image itself (these may be Opera only problems?). But these may just be personal preference issues which is why you rebuilt it like this, but usability-wise there’s still room for improvement.
September 3rd, 2008
I updated the prototype version to now close the zoom box with a click anywhere outside of it. Also, you can close it with the esc key.
September 3rd, 2008
I SALUTE YOU SIR! Well Done!
September 4th, 2008
John, could you provide the right syntax to have the shadow on fancy_outer rather than fancy_inner?
September 4th, 2008
@nic – Sorry but I don’t understand what you are asking. Can you explain?
September 4th, 2008
hi John, I’d like to be able to control the height of zoom_content and have a scroll bar for large chunks of text instead of a box that just grows to fit. I can do this in the .js div id=”zoom_content” style=”height:400px; overflow:auto;” but then I can’t have a smaller box Is there a workaround to this?
September 5th, 2008
This is great, thanks a lot!
At the moment JavaScript (script.aculo.us) doesn’t work for me inside the FancyZoom window. Isn’t it supposed to work in there, or is it supposed to work & I’m doing something wrong?
Also is it possible that once you’ve clicked something inside the window (e.g. a link or a button) the window closes? If so how would we do this?
September 5th, 2008
Looks like the prototype version works better with IE6 than the jQuery version. The jQuery version breaks up the divs into little bits. Both have no shadows. I know, IE6 sucks blah blah but people still use the damn thing.
With the prototype version and FireFox 2. the first image or div that is zoomed always comes from the far right of the screen for me. All zoom boxes after that originate from the correct starting point.
Nice work. I actually started working on this very thing yesterday, but now I don’t have too.
Since it’s based on FancyZoom do you have to pay a license for commercial use?
September 5th, 2008
I have having problems accessing form elements of a forms loaded with FancyZoom, (e.g. a login box) when I make a ajax request it cannot read changes to these elements (e.g. $(‘username’).value is blank)
This was working with another lightbox code I was using but I like the look of this one better. Any ideas on whats going wrong?
September 5th, 2008
Addition to the comment above, I’ve noticed that the zoom box contains a copy of the html it is displaying. I guess this is why I am having problems reading the values of the text fields because there are now 2 copies of the same text field of the page and it’s reading the unchanged original version. Is there any easy way of altering this?
September 6th, 2008
Just thinking… how easy or hard would it be to make it more like Quick Look? (Black semi-transparent window with the same HUD style title bar at the top)
September 9th, 2008
@Martin – Yeah it does copy the html. I haven’t thought through alternate ways but I’m sure there are. I will at some point.
@Jono – Wouldn’t be that hard. That is a cool idea.
September 9th, 2008
Thanks John, looking forward to future updates!
September 9th, 2008
Thanks John, I was hoping it would be quite straightforward.
September 9th, 2008
hi John, I have the same Q as Jono “Just thinking… how easy or hard would it be to make it more like Quick Look? (Black semi-transparent window with the same HUD style title bar at the top)”
September 12th, 2008
Looks very slick, only one issue: doesn’t work with Google Chrome :(
—Robin
September 12th, 2008
Would love to get this to work with Adobe’s Spry!! Any ideas
September 15th, 2008
Sexiest Fancy Box! I don’t care about ajax, but I really would love to see iframe support! Thanks.
September 16th, 2008
I love this script! I’m trying to use it with an image map and having some problems- clicking on anchor link in the image map does not seem to work, or am I missing something?
September 17th, 2008
No good that it does not work with ajax. What if I generate a list dynamically and want to show details of an item using FancyZoom? I can’t do it. Why does it not work if I do something like
new FancyZoom(“my_added_div”,{width:200});
where my_added_div is the div that I have added using JS after the page load?
September 29th, 2008