The Lightbox Effect without Lightbox

Feb 09, 2006 14 comments

Particle Tree posted an article the other day on how to modify the Lightbox javascript to work with regular divs and not just images. A few days before that article went up, I had the same bit of inspiration for Wayfaring.

We’re not afraid of pushing the envelope on the site, so if we like an idea, we’ll roll with it until too many of our users tell us it sucks. (That hasn’t ever happened incidentally)

Wayfaring Login

When I first started trying to figure out how to do this, I wasted a lot of time trying to hack the Lightbox code and it was ugly. I thought better of using code I wasn’t proud of, so here’s how I did it:


#overlay{ 
    background-image: url(/images/overlay.png);
    position: absolute;
    top: 0px;
    left: 0px;
    z-index: 90;
    width: 100%;
    height: 100%;
}

* html #overlay{
    background-color: #333;
    background-color: transparent;
    background-image: url(blank.gif);
    filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(
        src="/images/overlay.png", sizingMethod="scale");
}

#box{
    width:300px;
    background:#2d2d2d;
    padding:10px;
    border:2px solid #eee;
}

#close{
    position:absolute;
    top:-5px;
    right:-5px;
    cursor:pointer;
}

Most the css was lifted straight from the Lightbox css. Next is the HTML, which also includes Lightbox’s neat little close image.


<div id="overlay" onclick="hideBox()" style="display:none"></div>

<div id="box" style="display:none">
    <img id="close" src="/images/close.gif" onclick="hideBox()" alt="Close" 
         title="Close this window" />
    Here's a bunch of really sweet content!
</div>

And finally we have the javascript. The center function was lifted directly from here with a few slight modifications. Note: You also need Prototype for this script to work.


function showBox(){
    $('overlay').show();
    center('box');
    return false;
}

function hideBox(){
    $('box').hide();
    $('overlay').hide();
    return false;
}

function center(element){
    try{
        element = $(element);
    }catch(e){
        return;
    }

    var my_width  = 0;
    var my_height = 0;

    if ( typeof( window.innerWidth ) == 'number' ){
        my_width  = window.innerWidth;
        my_height = window.innerHeight;
    }else if ( document.documentElement &amp;&amp; 
             ( document.documentElement.clientWidth ||
               document.documentElement.clientHeight ) ){
        my_width  = document.documentElement.clientWidth;
        my_height = document.documentElement.clientHeight;
    }
    else if ( document.body &amp;&amp; 
            ( document.body.clientWidth || document.body.clientHeight ) ){
        my_width  = document.body.clientWidth;
        my_height = document.body.clientHeight;
    }

    element.style.position = 'absolute';
    element.style.zIndex   = 99;

    var scrollY = 0;

    if ( document.documentElement &amp;&amp; document.documentElement.scrollTop ){
        scrollY = document.documentElement.scrollTop;
    }else if ( document.body &amp;&amp; document.body.scrollTop ){
        scrollY = document.body.scrollTop;
    }else if ( window.pageYOffset ){
        scrollY = window.pageYOffset;
    }else if ( window.scrollY ){
        scrollY = window.scrollY;
    }

    var elementDimensions = Element.getDimensions(element);

    var setX = ( my_width  - elementDimensions.width  ) / 2;
    var setY = ( my_height - elementDimensions.height ) / 2 + scrollY;

    setX = ( setX &lt; 0 ) ? 0 : setX;
    setY = ( setY &lt; 0 ) ? 0 : setY;

    element.style.left = setX + "px";
    element.style.top  = setY + "px";

    element.style.display  = 'block';
}

That’s all there is to it! To make all of this goodness appear, you just need to call showBox().

The center function is a bit long, but most of that is just browser compatibility code. If you can make it any easier than this, I’m all ears, but I’m fairly satisifed with this solution.


14 comments


Tristan Dunn said about 5 hours later:

I just tried it out and there is a noticeable delay from when the box appears to when the overlay appears. You might want to preload the overlay image or switch to an opacity only solution.

Also, why is the overlay image 101×101? Sure, being 1×1 isn’t that big of a difference, but it would help with the load speed and save bandwidth over a long period of time.

Sean S said about 6 hours later:

Yes.

I knew there was an easier [lightweight] way—I’d actually attempted a similar result last summer with my personal blog and realized it was probably too much work to be worth it.

Thanks for doing the work. ;)

Reuben Whitehouse said about 8 hours later:

Very nice indeed.

Srinivasan R said about 10 hours later:

Nice one. Gotta try that one.

Srinivasan R said about 10 hours later:

Sorry for multiple comments. As Gerald mentioned, the comment form didnt clear in FF 1.5.0.1

Scott Walter said about 12 hours later:

Awesome. I thought the lightbox code was a little too heavy.

PJ Hyett said about 14 hours later:

Adding the rel=”lightbox” would have added more complexity and code to the solution. Don’t get me wrong, that is particularly useful when you want the effect working with multiple images on the page, but it’s a bit overkill for my purposes.

As far as why the form isn’t clearing the fields after you click submit, that’s a good question. I’ll see if I can fix that this morning.

John Zeratsky said about 15 hours later:

This is a killer effect. ManiacalRage.net uses it when he puts image links in posts, like on this post: http://maniacalrage.net/past/tags/japan/

Beautiful.

Chris said about 18 hours later:

Does anyone now why I would be getting the javascript error “Element.show is not a function”?

PJ Hyett said about 18 hours later:

My fault Chris. Element.show is a Prototype function. To remove that dependency, you just need to use the normal DOM method of making the div visible.

Chris said about 19 hours later:

Thanks,

It works just great after I added the latest version (1.4) of Prototype

PJ Hyett said about 19 hours later:

Glad to hear it. I think I also have the comment issues sorted out.

Bruno said 2 days later:

Great script, PJ. I played around with it and made some improvements (at least, they’re improvements for me).

Check out my version of Lightbox.js

It abstracts your functions into a Lightbox object, and allows for some customizations. Also lets you place more than one on a page. Hope it’s useful!

Jarkko Laine said 3 days later:

Way cool, PJ and Chris!

Tristan: The size of the image file actually doesn’t depend much on the physical size when the image consists only of one color. Actually using one pixel background images is often discouraged because many browsers go nuts when repeating an image over a million times.

Sorry, comments have been closed for this post.