ramka

The story of the lightbox

You have typed the word a thousand times. It names a box of light photographers kept in dark rooms, a script a blogger wrote in the last weeks of 2005, and the way images have opened on the web ever since. This is the story of the lightbox: the name, the parts, the clone wars, and the twenty-year handoff to the platform.

The room was dark first

Before it was JavaScript, a lightbox was furniture. A shallow box, a translucent white top, an even glow from inside. Photographers and photo editors spread strips of film and mounted slides across it and leaned in with a loupe. The room stayed dim on purpose. All the light in it belonged to the pictures. That is the whole idea, and it survived the move to software intact: dim the room, light the picture.

The furniture, at work. Photos by Priscilla Du Preez, Jason Leung and Jakub Żerdzicki on Unsplash.

The name was already doing rounds outside photography. Radiologists clipped X-rays to wall-mounted lightboxes. Advertisers sold backlit poster boxes under the same word. People with seasonal depression sit in front of a lightbox every winter morning. And in stock photography the word took one more turn that outlived the furniture: picking your selects off the light table became such a fixed ritual that agencies like Getty still call a saved collection of images a “lightbox”, a shortlist named after a piece of equipment most of their users have never touched.

So by the time the web needed a name for “darken everything except this one photo”, the metaphor was not just available. It was load-bearing in three industries.

A blog redesign names a pattern

In December 2005, a designer named Lokesh Dhakar was redesigning his blog. The new layout had a narrower content column, his post images overflowed it, and he did not want to resize every image each time he tweaked the design. So he replaced the images with thumbnails and wrote a script that opened the full-size photo above the page instead of navigating away. The account is preserved, with charming honesty, in the original repository’s README. Right before New Year’s, he emailed a few of his favorite design bloggers:

“I’ve written a little script to help people, mainly bloggers, handle large images. Its a little faux-popup effect with Javascript. It might be useful for you, or not, either way take a look.”
Lokesh Dhakar, email of December 29, 2005, as preserved in the Lightbox README
The man behind the email. Lokesh Dhakar, profile photo via his X profile.

It might be useful for you, or not. Eight days later WIRED wrote it up, describing the effect with a phrase that dates it precisely: a “shaded ‘mask’ layer of transparent PNGs” between the image and the page. In the IE6 era you could not trust a translucent CSS background, so the dim was literally a tiled picture of darkness. The script ran on Prototype and script.aculo.us, jQuery not having been announced yet, and it spread through del.icio.us the way things spread before GitHub existed: someone you trusted bookmarked it.

The entire API, 2005–2006
<!-- Lightbox, December 2005. The entire integration: -->
<a href="images/fort-funston.jpg" rel="lightbox" title="Dunes at Fort Funston">
  my photo
</a>

<!-- Lightbox 2, 2006. Name a set inside the brackets and you have a gallery: -->
<a href="images/one.jpg" rel="lightbox[roadtrip]">one</a>
<a href="images/two.jpg" rel="lightbox[roadtrip]">two</a>

Look at that integration surface for a second. The whole configuration is an HTML attribute. The link you already had, doing double duty. It degraded perfectly: no JavaScript, and the href simply opened the image, which is progressive enhancement so clean it still gets cited. And it planted a seed that took two decades to finish sprouting. From rel="lightbox" it is a straight line through class="thickbox" and today’s data--attribute galleries, the idea that your markup is the config file. What it is not, is composition. That distinction becomes this story’s ending.

The entire product, ten days old: huddletogether.com in January 2006, via the Wayback Machine. The downloads list is the tell: overlay.png, “80% opacity, black tile used to create shadow”, and loading.gif. (Click it. The images in this article open in a lightbox. Anything else would be a scandal.)

The script became so much bigger than its author that in 2007, when Dhakar published a charming illustrated chart of espresso drinks, TechCrunch’s write-up opened with its writer admitting he could not place the name: “I couldn’t figure out for the life of me where I’d heard his name before but I assumed he was famous for some reason.” The pattern had already outgrown the person. It was in the process of outgrowing the library too: “a lightbox” stopped meaning Lightbox.js and started meaning the entire category, the way kleenex stopped meaning Kleenex.

The other thing he is famous for. Coffee Drinks Illustrated by Lokesh Dhakar, CC BY-NC 3.0.

Here is what all that fuss looked like. Click a thumbnail.

Weekend photos
Posted December 2005 · 3 comments
Click a thumbnail. The dim, the white frame, the loading spinner, the caption in tiny Verdana, and the animated resize between differently sized photos are all faithful to 2005–2006 Lightbox, down to prev and next being invisible until you hover the photo’s left or right half. One period detail is simulated: the original’s dim was a tiled translucent PNG, not CSS opacity. And notice what your thumb already misses: no swiping, no pinch, no momentum. In 2005, you clicked.
Not a museum piece: the real Lightbox2 demo page, photographed live in 2026, banner for Lightbox 3 included.

The clone wars

ThickboxjsOnlyLightboxSexy LightboxEasyBoxGreybox ReduxCeraBoxprettyPhototinyLightboxLightBox Gone WildsimpleboxLyteboxSlideWindowFloatboxCeeBoxLightbox+TopUpFaceboxBumpboxMOOdalboxColorBox
SlimboxSuckerfish HoverLightbox ReduxImageZoomFancyboxLighter BoxAwesome BoxpiroBoxLiteboxmediaboxAdvancedHighslideFancy Zoom for PrototypeSexy Lightbox2SubModalShadowboxTALCIBoxYUI based lightboxWeebBoxLightviewEnlargeit!Milkbox
Slightly ThickerBoxLightbox2nyroModalGreyboxSmoothboxjQuery lightBox pluginRoeBoxControl.ModalTinyBoxMultiboxLightWindowImageboxPrototype WindowFancy Zoom for jQuerySWFboxSlightboxLeightboxModalBoxiBoxFancy Zoom
Sixty real clones, every name verbatim from the 2008 Clone Matrix. Hover to stop the flood.

Four months after that email, the cloning began. In April 2006 Cody Lindley released Thickbox, and the announcement came from the highest possible authority, John Resig himself, on the official jQuery blog:

“Cody Lindley just released a brand new version of Lightbox/Greybox called Thickbox. […] this release is completely unobtrusive - it uses the natural href, src, and title attributes to seed the box, when it pops up. Even if you don’t have Javascript enabled, it still behaves naturally.”
John Resig, jquery.com, April 24, 2006

Then the floodgates. Slimbox in October 2006, a 4 KB clone whose entire pitch was its file size. Fancybox in April 2008. Colorbox in March 2009. Greybox, Shadowbox, prettyPhoto, Highslide. For about five years, naming a lightbox meant choosing an adjective and appending “box”. By April 2008 the ecosystem was chaotic enough that one developer built a comparison matrix of more than thirty clones, opening with a sentence that captures the era: “Early 2006, a cool guy named Lokesh Dhakar introduced Lightbox […] Since, every once in a while, someone comes up with their own take at this concept, using this or that javascript library (jQuery, Prototype, Mootools, YUI, you name it).” Every JavaScript framework of the era needed its own clone, because plugins could not cross framework lines.

The Lightbox Clones Matrix, still online today. Every pill in the wall above is one of its rows.

What did they compete on? Kilobytes, transitions, and content types: iframes, inline HTML, Flash, video, AJAX. And since the markup-as-config API had nowhere to grow, differentiation moved into options objects, which grew, and grew, and never stopped growing. The case for a headless React lightbox traces where sixty-option config objects eventually lead; this era is where they were born.

Lightbox, modal, dialog, popup: who is who

The clone era also scrambled the vocabulary, and it has never fully recovered. If you have ever lost a naming argument in a design review, here is the untangling:

Popup
The ancestor, and the villain of the origin story. A separate browser window via window.open(), so despised by 2005 that “faux-popup”, Dhakar’s own words, was a selling point. The word now mostly means marketing overlays, which inherited the reputation.
Dialog
A window that lives inside the page and talks to you. The generic pattern, and since 2022 an HTML element.
Modal
Not a thing but a property: a dialog is modal when the rest of the page stops working until you deal with it. “A modal” as a noun is the industry’s most successful grammatical error.
Lightbox
A modal dialog whose occupant is media. Dim the room, light the picture, navigate between pictures. If it has a backdrop and a photo, it is a lightbox, whatever the marketing site calls it.
Carousel
The strip of slides itself, which can live inside a lightbox or directly on a page. A lightbox is usually a modal wrapped around a carousel, which is why it inherits the accessibility obligations of both.

The anatomy, and the names that stuck

Strip away twenty years of visual fashion and the machine has barely changed. The parts the pattern settled on in its first years are the parts every implementation still has:

Backdrop. The dimmed layer between you and the page. Theater calls it a scrim; in 2005 it was a tiled PNG; CSS now ships one for every top-layer element as ::backdrop. Clicking it closes.

Most of these parts were in place by 2006; the stage and the filmstrip arrived with touch. All of them survived every rewrite since, which is why headless libraries name their primitives after them.

This is also why, when we named ramka’s composable lightbox primitives, we mostly did not have to invent anything. Backdrop, Stage, Slides, Counter, Caption, Close, Thumbnail. The pattern named its own organs decades ago. A component library’s job is to hand them to you individually instead of fused together.

The mobile turn

Then the iPhone shipped, and the pattern’s core assumption, a mouse, quietly died. Look back at the 2006 recreation above: previous and next appear when you hover the photo’s halves. There is no hover on glass. An entire generation of lightboxes had hidden their navigation inside an input that touchscreens do not have.

The rewrite arrived from an unexpected direction: not a famous framework author but PhotoSwipe, started in 2011 at Code Computerlove, a digital agency in Manchester, and built touch-first from day one. Swipe to navigate, pinch to zoom, momentum that kept moving after your finger left. In March 2014 the agency handed the project to Dmitry Semenov, who had already written Magnific Popup (that is two of the most-deployed lightboxes ever, one author), and his rewrite became the standard everyone else chased. The price of the new features was steep, though rarely itemized: swipe, momentum and rubber-banding are platform physics, and a JavaScript carousel has to reimplement all of them, frame by frame, on the main thread. Why native scrolling beats transform carousels is this story’s sequel about exactly that bill coming due.

The design north star also changed. The clone era imitated other websites; the touch era imitated the iOS Photos app: pull the photo downward to dismiss it, morph it back into the thumbnail it came from. And in an ending nobody would have predicted in 2013, Semenov eventually deprecated Magnific Popup with advice that closes the loop on this whole section of history: use a native <dialog> element if you need a basic popup. The author of the jQuery era’s favorite lightbox now tells you to start with an HTML tag.

dimsemenov.com today. The era’s favorite lightbox, pointing you at an HTML element.

The lightbox that caused a constitutional crisis

In 2014 the lightbox got its strangest historical footnote. Wikimedia rolled out MediaViewer, a lightbox for Wikipedia’s article images, and the editing communities pushed back hard, arguing it was not ready. Surveys and requests for comment on English Wikipedia, Wikimedia Commons and German Wikipedia reached consensus to turn it off by default. The Foundation declined. On German Wikipedia, an administrator disabled the viewer anyway, by editing the site’s Common.js.

What happened next escalated past software entirely. On August 10, 2014, the Foundation created a brand-new user right called superprotect and used it, the same day, to lock that JavaScript page above the reach of the site’s own administrators. The Signpost, Wikipedia’s internal newspaper, explained the new power flatly: “‘Superprotect’ is a level above full protection, and prevents edits by administrators.” The German community responded by blocking the Foundation’s deputy director for a month. An open letter against the move collected nearly a thousand signatures. The protection came off the page that same August; the superprotect right itself was abolished in 2015.

Somewhere between “dim the page” and “show the next photo”, an image overlay had triggered a constitutional crisis in the largest collaborative project in human history. No other UI component can put that on its résumé.

And it won: MediaViewer, photographed on the Apollo 11 article in 2026. Counter, arrows, caption, backdrop: a lightbox. (Photo: NASA, public domain.)

The platform catches up

Here is a different way to read the clone-era feature matrices: as a stack of bug reports against the web platform. Centering a box. Dimming a page. Trapping focus. Closing on Escape. Every lightbox since 2005 had shipped the same few hundred lines of workaround, and the platform eventually absorbed them: the <dialog> element shipped in Chrome in 2014 but became usable in earnest in March 2022, when Safari 15.4 and Firefox 98 shipped it weeks apart. With it came the top layer, which ended the z-index arms race, and ::backdrop, which turned the dim from a tiled PNG into a pseudo-element the browser draws for you. The inert attribute made “the rest of the page stops working” a one-word contract.

The gallery half followed the same road. CSS scroll snap, cross-browser since 2019, made “a scroller that stops one photo at a time” a stylesheet rule instead of a physics engine. overscroll-behavior tamed the edges. Native scrolling brought platform momentum with it, no reimplementation required. And the View Transitions API is currently absorbing the last showpiece: the morph between thumbnail and full photo that the touch era copied from iOS. Twenty years of library features, standardized one spec at a time.

What the platform cannot absorb is the part that was never generic: your markup, your design, your captions and buttons and layout. Which is precisely the part the current generation of lightboxes, the headless generation, hands back to you.

Twenty years in one scroll

  1. Before the web
    The light table

    Photographers sort slides on a box of even white light, loupe in hand. Dark room, lit picture.

  2. Dec 2005
    Lightbox.js

    Lokesh Dhakar overlays full-size photos on his blog instead of resizing them, and emails a few design bloggers.

  3. Jan 2006
    The snowball

    WIRED writes it up within a week; del.icio.us does the rest. The name starts to outgrow the script.

  4. Apr 2006
    Thickbox

    Cody Lindley’s jQuery take, announced by John Resig on the official jQuery blog. The clone era opens.

  5. 2006–2009
    Everything-box

    Slimbox (Oct 2006), Fancybox (Apr 2008), Colorbox (Mar 2009), plus prettyPhoto, Greybox, Shadowbox, Highslide. By April 2008 one comparison table tracks more than 30 clones.

  6. 2011
    PhotoSwipe

    A Manchester digital agency builds the first famous touch-first gallery. Swipe, pinch and momentum become table stakes.

  7. Mar 2014
    The handoff

    PhotoSwipe passes to Dmitry Semenov, author of Magnific Popup. Months later Chrome ships the <dialog> element.

  8. Aug 2014
    The Wikipedia crisis

    Wikimedia’s MediaViewer rollout triggers the superprotect standoff. A lightbox becomes a governance question.

  9. 2019
    CSS scroll snap

    The gallery half of the pattern, snapping a scroller one photo at a time, becomes a platform feature.

  10. Mar 2022
    <dialog> everywhere

    Safari 15.4 and Firefox 98 ship it weeks apart. The modal half of the pattern is now an HTML element with a ::backdrop.

  11. Now
    The headless era

    The behavior comes from a library; the markup and every visible pixel belong to the application.

Where the story goes next

Four eras, four architectures. An attribute on a link, degrading gracefully to a page load. A jQuery plugin with an options object. A React component with a bigger options object. And now primitives you compose, where the library ships the behavior and the pixels are yours. The old eras never fully leave, though. They linger in production. WebAIM’s 2026 scan of the top million homepages still detects the original Lightbox script on nearly 39,000 of them, averaging 25.7 percent more accessibility errors than the mean, with FancyBox at 60.3 percent more. History, in this pattern, is not something you read about. It is something you inherit and something screen readers still trip over.

ramka is our contribution to the current chapter: a headless React lightbox built on the parts this pattern spent twenty years discovering: a real scroller for the slides, real dialog semantics for the modal, and every visible piece of chrome rendered by you. If the history made you want to build one, the docs take about ten minutes. Dim the room. Light the picture.