My site was recently featured in a web magazine for an article I had written on a CSS only content slider. I noticed another CSS only article featured was a CSS only lightbox. After investigating the code I learned a few things but I felt the overall presentation could be improved upon and that I could also use my technique of using URL hash tags as CSS state variables as another solution. I know CSS only lightboxes have been done before but I offer you another method.


CSS Only Lightbox/Shadowbox Example

If you want to skip the article and go straight to the final product view my CSS Only Lightbox/Shadowbox Demo.

Note: You will need to use Safari/Chrome, Opera 11 or Firefox 4 in order to view the transition effect. It will work in Firefox and IE9 sans the animation.


I'll start out this article by stating that it won't work in Internet Explorer, and that this is really just a proof of concept. It would, however, work in Internet Explorer had it supported the :target pseudo selector. It should be noted that IE9 will support this selector as well as quite a few others.

Clickable Transparent Background

The first thing people come to expect from a lightbox/shadowbox solution is the ability to click a semi-transparent background and have the window close. I accomplished this by absolutely positioning an anchor on the page with an href of #close I'll go into more detail on how this works later.

<a href="#close" class="lightbox-bg" title="Click to close"></a>

Below is the CSS for our semi-transparent background. You'll notice that it spans the entire viewport and that it has a default opacity of 0 to hide it.

.lightbox-bg { background: #000; height: 100%; width: 100%; opacity: 0; outline: 0px; position: absolute; left: 0px; top: 0px; z-index: 2; }

Modal Window

The next major piece of a lightbox/shadowbox solution is the media itself. Most people come to expect the modal window to be centered both vertically and horizontally. From what I can tell, the method I used to accomplish this was created by which uses negative margins which are exactly half of the height/width of the modal window.

.lightbox-content { background: #fff; height: 0px; width: 0px; margin: -275px auto auto -275px; overflow: hidden; position: absolute; top: 50%; left: 50%; z-index: 3; }

Opening our Lightbox

And now probably the most interesting part of the code. The part that actually makes it open! This part uses one of my favorite additions to CSS3, CSS Transitions. Currently, they are supported by all Webkit browsers (Safari & Chrome for example) Opera 11, and the soon-to-be released Firefox 4.0.

The code works by animating the transition of values in specific properties. For instance if an element, by default, has an opacity value of 0.0 and it's animated value is 0.8 it will create a transition effect from 0.0 to 0.8 in the specified amount of time you pick. In my case I chose .2s which means .2 seconds.

.lightbox:target .lightbox-bg { left: 0px; opacity: 0.8; -o-transition: opacity .2s linear; -webkit-transition: opacity .2s linear; -moz-transition: opacity .2s linear; }

Displaying the modal window works in a similar fashion. Like Shadowbox, I wanted my modal window to have a size increasing effect upon opening. I did this by transitioning the height and width of the window. By default I set these values to 0px and then increased the size to 550px

.lightbox:target .lightbox-content { height: 550px; width: 550px; -o-transition-property: height, width; -o-transition-duration: .2s, .2s; -o-transition-delay: .3s, .3s; -webkit-transition-property: height, width; -webkit-transition-duration: .2s, .2s; -webkit-transition-delay: .3s, .3s; -moz-transition-property: height, width; -moz-transition-duration: .2s, .2s; -moz-transition-delay: .3s, .3s; }


The close effect is very similar to the open effect except it does the reverse action. For the close effect I created transitions for opacity, height and width.

#close:target .lightbox { left: -100%; -o-transition-property: left; -o-transition-duration: .0s; -o-transition-delay: .7s; -webkit-transition-property: left; -webkit-transition-duration: .0s; -webkit-transition-delay: .7s; -moz-transition-property: left; -moz-transition-duration: .0s; -moz-transition-delay: .7s; } #close:target .lightbox-bg { opacity: 0; -o-transition-property: opacity; -o-transition-duration: .3s; -o-transition-delay: .3s; -webkit-transition-property: opacity; -webkit-transition-duration: .3s; -webkit-transition-delay: .3s; -moz-transition-property: opacity; -moz-transition-duration: .3s; -moz-transition-delay: .3s; } #close:target .lightbox-content { height: 0px; width: 0px; -o-transition-property: height, width; -o-transition-duration: .2s, .2s; -webkit-transition-property: height, width; -webkit-transition-duration: .2s, .2s; -moz-transition-property: height, width; -moz-transition-duration: .2s, .2s; } #close:target .lightbox-content div { opacity: 0.0; -o-transition: opacity .2s linear; -webkit-transition: opacity .2s linear; -moz-transition: opacity .2s linear; }

The :target Pseudo Selector

As promised in the beginning of the article, I'll explain more about how the :target pseudo selector is being used. The :target selector is an interesting part of CSS in that it's capable of being aware of what hash is currently present in the browser's URL. A has is something like this: /page.php#hash

In the CSS I'm able to apply different CSS styling to elements based on what has is currently being used. In this case I have a hash for #window1, #window2, #window3 and #close, the two states of my CSS only lightbox.

The HTML needed to accomplish this looks something like this:

<div id="close"> <div id="content"> <a href="#window1">Open Window 1</a> <a href="#window2">Open Window 2</a> <a href="#window3">Open Window 3</a> </div> <div id="window1" class="lightbox"> .... </div> <div id="window2" class="lightbox"> .... </div> <div id="window3" class="lightbox"> .... </div> </div>

The CSS I use to target these specific hashes looks like this:

.lightbox:target .lightbox-bg { .... }

Notice the :target in there? That's the magic.

Further Reading

Well, if you've made it this far down my lengthy article I congratulate you. Here's a few links for further reading on topic if you're interested in tinkering with this on your own: