How to Make Better Modal Windows with Lightbox
Published February 12th, 2006 in GeneralIt started with LightboxJS by Lokesh Dhakar; he created a script you could use to overlay images on your page. Then ParticleTree modified the script to let you create a modal window. Then PJ Hyett posted a stripped down, simplified version of the script.
I liked all of those, and I think the lightbox/modal dialog window is a good UI widget to have. So I created my own version of the script. It’s more abstracted than any of the previous ones, and lets you create a modal window (or more than one) on a page really easily.
Download the source. It including the scripts, the css and the various images you’ll need. (02/13 NOTE: updated sources to fix some IE bugs).
Here’s how you use it:
Include the scripts and the css in your page:
Then, create a hidden div somewhere on your page that holds the contents of your modal window, like this:
Then create a link that triggers the lightbox:
<a href="#" onclick="new Lightbox.base('mybox'); return false">Open the lightbox!</a>
That’s it. The script will automatically add everything else, including the little close icon in the upper left of the lightbox.
Options:
– you can choose to have the lightbox close when the user clicks anywhere else on the dimmed-out screen (I call this area the overlay). This is off by default. To turn it on, do this:
new Lightbox.base('mybox', { closeOnOverlayClick : true })
– you can specify the id of an external control to close the lightbox (in addition to the close-box icon), like this:
new Lightbox.base('mybox', { externalControl : 'cancel'})
- by default the lightbox is assigned the class of “lightbox”. You can change this if you want, as long as you remember to change the css accordingly.
new Lightbox.base('mybox', { lightboxClassName : 'myClassName'})
You can do as many of these as you like on a page. The script closes any that are open before opening a new one, so can only have one open at a time. The function that closes any open lightbox windows is Lightbox.hideAll(). You can call this anytime to close all open lightbox windows.
Feel free to reuse, distribute and modify this code as you wish. If you do something cool with it, I’d love to know. Remember that I whipped this up this morning while listening to A Prairie Home Companion, and also that I’m far from an expert in Javascript, so it is likely to have to kinks that need working out.
UPDATES:
Made some fixes thanks to some feedback in the comments. The script now uses no images, and should work as expected in IE6 (and 7, if you have it).
62 Responses to “How to Make Better Modal Windows with Lightbox”
- 1 Pingback on Jul 24th, 2007 at 10:59 am
Your version has a major issue. When I scroll down the page, then click your demo link, the overlaying opacity background image doesn’t cover the entire browser window. It only covers what you’d see if you hadn’t scrolled the page at all. This is in Firefox 1.5 and Safari for OS X.
In IE6 for Windows, the opacity background doesn’t display at all.
Hmm…good point. Actually it looks like PJ’s version has that problem too. It’s because the overlay div is set to 100% height and width, but that just takes into account the original viewable area of the window. I’ll see what I can do.
Fixed! Just needed to add some code to stretch the overlay all the way down. I’m still looking into the IE6 windows thing. I’ll post the new source later today.
Your update says it should work as expected in ie6 & 7. Not sure if you put that up there before your last comment or not.
Anyway, I get the popup window content, but not the background overlay in IE6 Win.
Darn! I can confirm that the updated code does not work in IE 6.
Sorry guys, missed these comments in my moderation queue… I’ll take a look as soon as I can.
The example link doesn’t seem to be going anywhere.
Yep..some of the files got wiped out when I switched themes this week.
Alright, I’ve got it partly figured out…something in K2’s stylesheet (the new Wordpress theme I’m using) is causing the lightbox div to center incorrectly on the page. Having trouble pinpointing exactly what, though…I know if I disable the entire K2 stylesheet the lightbox appears as it should. I’ll keep working on it…but the script should work fine on most other sites.
Thanks so much! I’m really looking forward to using it. I have one weird problem that I wondered if you knew how to overcome: I’m using a Yahoo! Map and I want to use the lightbox for users to fill out a form. The lightbox shows on top of the yahoo map in Firefox(which is what I want, but the lightbox overlay shows behind the map in IE which means you can’t read the document. You can find an example here: www.bittercyclist.com/maps/accmap.php
One more thing… I found an article that basically says you can’t use lightbox with DIVs like the Yahoo Map in IE because IE has problems. See http://www.brainjar.com/css/positioning/default5.asp. This article explains that z-index just doesn’t work right with DIVs containing flash, for example. Any work around?
Hi Brandon, I think it has to do with the fact that the z-index css attribute has not effect on embedded Flash objects. So even though the overlay has a higher z-index than the Flash movie (in your case, the Yahoo Map), the Flash gets stacked above everything else.
One way to get around this (I think), would be to modify lightbox.js to automatically look for any flash objects and hide them when the lightbox is activated (and then show them again when it’s closed).
This is actually pretty easy to do, thanks to prototpye.js. It would look something like this:
//first put all your flash in divs with a class name of your choice//in this case i'll use
<div class="flash">
flashObjects = document.getElementsByClassName('flash')
flashObjects.each(function(object){
Element.hide(object);
})
</div>
This would hide them (just put it in the “initialize” function of Lightbox.base).
To show them again, you’d do:
flashObjects = document.getElementsByClassName('flash')
flashObjects.each(function(object){
Element.show(object);
})
And put that in the Lightbox.base.hideBox() function.
Hope that helps.
Thanks so much! I’ll try it out at lunchtime! Unfortunately, I have to work now (non-web development).
It works, but the effect of the light box is totally diminished. I tested the lightbox with the Yahoo AJAX and Google versions, and there is no problems.
Thank you very much for the script. I love how you have abstracted things to make it easier to use. But unfortunately I seem to have the same problem in IE6 on Windows XP. I get the pop up content, but the background overlay does not cover the page, it only seems to cover a very small portion of the page.
I’ve been struggling a little bit with Lightbox.js and have even seen it crash Mozilla completely. Your implementation looks interesting, I am testing it now and I see that in Opera 8.52 the background does not completely disappear when I close the lightbox overlay. I have either scroll the window to get back the native page colors, or change focus to another window and back again.
I’ve been playing around with Bruno’s script in IE 6 and Firefox 1.5. Everything works fine in Firefox 1.5, but in IE6 the overlay does not cover the entire page and in some cases I don’t see it at all. The problem occurs in IE when you put a ‘lightbox’ div (div that you will popup using lightbox) within another div that does not cover the entire page. If you put the lightbox code right after the ‘’ tag and make sure that it’s not within any other div, then you shouldn’t have problems. Unfortunately I could not do that since I created web pages on the fly from a servlet and moving the divs to the top would require a lot of changes.
Also in IE, selects aren’t hidden and display above the ‘lightbox’ div, so I fixed that by hiding all selects within the page then showing any selects within the ‘lightbox’ div.
Another issue I saw in IE is you could scroll up and down the page and since the lightbox doesn’t cover the entire length of the page, I had to prevent the user from being able to do so. So I prevented that from using code I’ve seen in other lightbox implementations.
So after a little bit of work and testing, I made the lightbox work on my system in IE 6 and Firefox 1.5 no matter if you put the ‘lightbox’ div within another div. I also check for CSS styles top, left, width and height and added code to work with percentage and/or pixel values. This is something I just hacked together, so there are definitely many enhancements, fixes one could make. The code is shown below.
Lightbox code:
weird in IE6 sp2, no overlay, no centering.
Matt, can you host/paste your script somewhere ? because when I copy it from here, it’s all messed up ( no formating ), also, there are errors in your js, run FF Javascript console to catch them
Take a look at what these guys have done – http://www.hdosport.com/proddetail.php?prod=Garmin-Forerunner-305&cat=54 – they’ve got flash in a lightbox.
Thanks for this – great stuff!
Apologies if this isn;t the place for this, but I’m trying with RoR 1.1 to use the above lightbox code to get a login box working. The login works fine, but I can;t get the window to close/page to update. Any ideas how I could do that?
Thanks
thanks for all the great info; I am having a different lightbox issue and wonder if you could advise me:
I want the overlay only to cover the content of a div (called “belowmenu”) which I have already positioned on the screen, rather than blacking out the entire page.
I have several motives for this: there is a flash menu atop the whole page which I’d prefer not to turn off, so it seems better just to position lightbox’s overlay not to interfere with it at all; the “belowmenu” div is fixed width, narrower than the page and autocenters itself, so it would be nice for the overlay to follow along inside it; and mostly design considerations: I’d like only the one div to darken.
I think this shouldn’t be so hard for someone who knows how the code works better than I… but I’ve spent a while tinkering with it and have decided to turn to the experts rather than continue to haphazardly butcher elegant code.
Thanks for your input.
If you are still having trouble with the overlay and IE6, perhaps this forum discussion would be of help: http://www.huddletogether.com/forum/comments.php?DiscussionID=8.
A simple modification to the CSS file solved the problems with the overlay not covering the screen in IE6. Just add the following simple code:
body {margin: 0;
padding: 0;
height: 100%;
width: 100%}
Implemented the lightbox and overlay effects to several parts of my website and it looks great. Thanks for all the help.
You can check it out here: http://www.planjam.com/date.php
That’s a pretty sweet trick. Thanks for insight. Worked out great!!
I’ve found some problems, would benice if you can reply or solve!
– The TAB key doesn’t works? I’ve put two but the TAB key don’t go from one to other, are needed to use the mouse.
– end user can’t move the box/window.
– end user can’t resize the box/window.
– would be nice including a caption/title
– how can deactivate the x close icon?
Thanks very much for so good script!
Guillermo
could you give an example how to use an external site with the lightbox? it is not very handy to have the div inside the code
thx
Thanks for the script Bruno, works great.
I had to load external files into the lightbox so I extended the script a bit to do this with iframes. It works like this:
new Lightbox.base(‘mybox’, { url : ‘http://www.url.com’, width : 400, height : 500})
In this case ‘mybox’ doesn’t refer to an existing element. A new div with id ‘mybox’ is created. It wraps the iframe. Below is the code that was modified.
//start by hiding all lightboxes
LightboxMini.hideAll();
this.options = Object.extend({
lightboxClassName : ‘lightbox’,
closeOnOverlayClick : false,
externalControl : false,
url: false,
width: 500, // default width
height: 500 // default height
}, options || {} )
if (this.options.url) {
//create the iframe
var iframe = document.createElement(“iframe”);
iframe.style.width = this.options.width ‘px’;
iframe.style.height = this.options.height ‘px’;
iframe.id = element ‘_iframe’;
iframe.name = element ‘_iframe’;
iframe.src = this.options.url;
//create a container for the iframe
var container = document.createElement(“div”);
container.style.width = this.options.width ‘px’;
container.style.height = this.options.height ‘px’;
container.id = element;
//add iframe container
container.appendChild(iframe);
bod = document.getElementsByTagName(‘body’)[0];
bod.appendChild(container);
}
this.element = $(element);
//create the overlay
Thanks for the awesome script! I’m having a small problem tho:
I’m creating a 1px stroke that surrounds the body of my site using a table with height and width of 100%. It’s the only way I’ve been able to get it to work cross browser. However, doing this causes the overlay DIV to not work on IE!
Anyone know a fix, or a better way to create a stroke that actually works in IE6?
Thanks,
Trevor
Solved it, incase by some chance anyone else has this problem. You just have to modify lightbox.js to make sure that the overlay element is inserted at the beginning of your document. For me, all my documents start with a table with ID of “stroke”, so I changed it to:
new Insertion.Before(“stroke”, “”);
and it works!
Trevor
this fix for IE:
body {margin: 0;
padding: 0;
height: 100%;
width: 100%}
doesn’t help when lightbox is opened below first screen.
For example you have long page and scroll 2-3 pages, at the bottom you click on link, picture/content opens up, but lightbox effect (see-through layer) isn’t behind your new content, but up on the first screen of your page
anyone have working fix for ie 6?
also,
also href=”javascript:;” onClick… doesn’t work on IE, only href=”#”
any other options that works in IE
-: FRAMESET ISSUE :-
First of all,this is one of the best and simple lighbox i found, Congratulations specially the launcher, not a link with rel and other stuff, just an onclick and i’ts done, very helpfull.
Thanks again., And Now:
When a FrameSet is… well, “set” into the page, and the lighbox is launched in one of them, the 100% height does not work at all, maybe because the javascript works with the window Height, not with the frame height …
It’s ok that the lightbox dont cover all the page but the frame, but the height is wrong.
Anyone got a solution for this ??
-: Other Thing :-
Is there a way to disable the closer button?
Cause the div close when a dynamic process is done, the time is relative. I’ts working just perfect, but i don’t need the closer button.
Any help Please?
Again Congratulations and Thanks a lot !
Thanks again but i just found something … in IE 6 the SELECT elements shows over the lightbox … is there a FIX to hide or put behind?
Please … all my work depends on it …
just kidding.
Thanks
I also noticed the IE6/SELECT issue. Is there any fix for this?
OK, using the technique I found here (http://www.shepherdweb.com/2007/02/14/z-index-ignored-for-select-element-in-ie-6-workaround/), I came up with this solution:
Change line 36 of lightbox.js to this:
new Insertion.Before(this.element, “”);
Then add this selector to your CSS file:
#overlay iframe
{
display:none;/*sorry for IE5*/
display/**/:block;/*sorry for IE5*/
position:absolute;/*must have*/
top:0;/*must have*/
left:0;/*must have*/
z-index:-1;/*must have*/
filter:mask();/*must have*/
width: 100%;/*must have for any big value*/
height: 100%;/*must have for any big value*/;
}
Good luck!
Looks like the special characters are messing with my post. Basically, change line 36 to add an iframe inside the overlay div using the code from the site I mentioned. Wrap the iframe declaration with an “if” for IE.
With IE it does not cover all elements, if there are textboxes – it is left uncovered.
I get a ‘class’ is not defined error in Firefox and IE for this line in lightbox.js
Lightbox.base = Class.create();
It is not working for me at this point. What do I need to change?
Hey,
I love what you’e doing!
Don’t ever change and best of luck.
Raymon W.
Looks Like Dallas is in trouble!
Phoenix might end up blowing them all away.
PHX vs. Det. Hmmm..Could be interesting?
I’m not quite understanding what all
this is supposed to be about?
Must be me or something…
How green is the grass on the other side of the fence?
Not much. Don’t believe it I tell you.
Jerry
Hey,
Really nice site you got here.
I’ll come back more often and check it out.
Peace!
Great script!
In some cases, you want to continue with another action (navigating to another page for example) once the user has read the message box and closed it. I have modified your script a little so that you can pass a callback function that is executed after the box closes:
The callback function is passed as an option so your option initialization will look like this:
this.options = Object.extend({
lightboxClassName : ‘lightbox’,
closeOnOverlayClick : false,
externalControl : false,
callbackFunction : function(){}
}, options || {} )
Then your hideBox function will look like this:
hideBox : function(evt){
Element.removeClassName(this.element, this.options.lightboxClassName)
Element.hide(this.element);
//remove the overlay element from the DOM completely
Element.remove(‘overlay’);
this.options.callbackFunction();
return false;
},
Hope this is useful
Hey guys,
The updated version gives me an ugly popup blocker in IE6 with sp2. It does not work on my layout when I try to port it. Anyone has a fully compatible version? Got link?:-)
Interesting Post.
I’d never heard that before.
Barney
hi guys! what if i wanted to open a different html file for the popup instead of encoding all the content in one webpage. just like new window popups, they call a new html file to popup contents. please help. i like the lightbox script, i just want a separate file for each content of my popups.
thanks!
Just tried this (7/6/07) in IE6 and it’s not working properly. I did something similar in my app (a “working indicator” that is partly based on lightbox)—I had to use an Iframe and size it when it displayed with some javascript.
I’ve been pretty stressed lately. This site helps to ease the anxiety!
Thanks a lot and take care of yourself.
Mrs. McNamara
sorry for being weird, at the moment i am using popup window to open php files, is there anyway i can open php files in this hidden div, its just bit frustrating to see people talking about lightbox, but no one is giving a clear example using against calling some php files inside the div, using this beautifull scripted lightboxes/punches on your face. i got knocked out. lol
Here’s a very minor fix that breaks the script if you have multiple dialogs on a single page (in Safari). The issue is that you end up with multiple “close” images on the page with the same ID (‘close’), so on the hide of the div, you need to also remove the close image from the DOM. Otherwise safari’s doesn’t follow the observer pattern.
in hideBox() after Element.remove(‘overlay’); add:
Element.remove(‘close’);
Thanks for this.
This is great stuff. Thanks for the corrections and update!
Wow, there is some really nice info here.
I’ll definitely come back soon to see everything.
Way to go!
Joey
Looks good mate but in safari beta v.3.0.3 (g4) when I click the first demo link I can’t close the popup box.
Nice script.. I was especially intreged by the claim “even an i-frame” in the demo. I’ve downloaded the script, and added a link to a page which does indeed load an iframe into the lightbox.
My question is: from the .aspx page within this iframe, how can I close the lightbox when a button is pressed? my iframe aspx script is a file browser, and once someone selects a file, I need them to click a button and a) have the selected file value passed back to my original script (the one that starts the lightbox) and b) have the lighbox closed.
Any advice would be appreciated.
No matter what I try I cannot get Safari 2 to play well with this. As soon as there are multiple lightboxes on a single page, the close window button doesn’t work. I tried the suggestion above:
in hideBox() after Element.remove(‘overlay’); add:
Element.remove(‘close’);
But it is not working – does anyone have any ideas?
Hi, guys
i have good solution for IE (100% height&width)
#overlay {
height:expression(document.body.clientHeight);
width:expression(document.body.clientWidth);
}
lilidronerc