[Article] Details/summary lightboxes in pure HTML + CSS

 

💤 Tired: <dialog>-based HTML+CSS lightboxes

A few years ago I implemented a pure HTML + CSS solution for lightbox images, which I’ve been using on my blog ever since. It works by pre-rendering an invisible <dialog> for each lightboxable image on the page, linking to the anchor of those dialogs, and exploiting the :target selector to decide when to make the dialogs visible. No Javascript is required, which means low brittleness and high performance!

It works, but it’s got room for improvement.

One thing I don’t like about it is that it that it breaks completely if the CSS fails for any reason. Depending upon CSS is safer than depending upon JS (which breaks all the time), but it’s still not great: if CSS is disabled in your browser or just “goes wrong” somehow then you’ll see a hyperlink… that doesn’t seem to go anywhere (it’s an anchor to a hidden element).

A further thing I don’t like about it is it’s semantically unsound. Linking to a dialog with the expectation that the CSS parser will then make that dialog visible isn’t really representative of what the content of the page means. Maybe we can do better.

🚀 Wired: <details>-based HTML+CSS lightboxes?

Here’s a thought I had, inspired by Patrick Chia’s <details> overlay trick and by the categories menu in Eevee’s blog: what if we used a <details> HTML element for a lightbox? The thumbnail image would go in the <summary> and the full image (with loading="lazy" so it doesn’t download until the details are expanded) beneath, which means it “just works” with or without CSS… and then some CSS enhances it to make it appear like a modal overlay and allow clicking-anywhere to close it again.

Let me show you what I mean. Click on one of the thumbnails below:

A champagne-coloured French Bulldog sits with her tongue sticking out.

Larger image: a champagne-coloured French Bulldog sits in a basket in the corner, with her tongue sticking out.

Close-up cross-section of a BLT sandwich on toasted bread.

Larger image: a thick, delicious-looking BLT sandwich on toasted bread, wrapped in paper and sliced down the middle.

Dan, a white man with a beard, wearing a rainbow bandana, points to a white building behind him.

Larger image: Dan, a white man with a beard, wearing a rainbow bandana and a black t-shirt, points to a building in the background whose sign identifies it as Stanton Harcourt Cricket Club.

Each appears to pop up in a modal overlay, but in reality they’re just unfolding a <details> panel, and some CSS is making the contents display as if if were an overlay, complete click-to-close, scroll-blocking, and a blur filter over the background content. Without CSS, it functions as a traditional <details> block. Accessibility is probably improved over my previous approach, too (though if you know better, please tell me!).

The code’s pretty tidy, too. Here’s the HTML:

<details class="details-lightbox" aria-label="larger image">
  <summary>
    <img src="thumb.webp" alt="Alt text for the thumbnail image.">
  </summary>
  <div>
    <img src="full.webp" alt="Larger image: alt text for the full image." loading="lazy">
  </div>
</details>

The CSS is more-involved, but not excessive (and can probably be optimised a little further):

.details-lightbox {
  summary {
    display: block;
    cursor: zoom-in;

    &::before {
      content: '';
      backdrop-filter: none;
      transition: backdrop-filter 0.5s, background 0.2s;
      background: transparent;
    }
  }

  & > div img {
    max-width: 95vw;
    max-height: 95vh;
    box-shadow: 0 0 12px #fff6;
    opacity: 0;
    transition: filter 0.3s, opacity 0.6s;
    filter: blur(6px);
  }

  &[open] > div {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 110;
    pointer-events: none;

    img {
      opacity: 1;
      filter: none;
    }
  }

  &[open] > summary {
    cursor: auto;

    &::before {
      content: '';
      background: #000a;
      backdrop-filter: blur(6px);
      position: fixed;
      top: 0;
      left: 0;
      width: 100vw;
      height: 100vw;
      z-index: 109;
    }
  }
}

body:has(.details-lightbox[open]) {
  overflow: hidden;
}

Native CSS nesting is super nice for this kind of thing. Being able to use :has on the body to detect whether there exists an open lightbox and prevent scrolling, if so, is another CSS feature I’m appreciating today.

I’m not going to roll this out anywhere rightaway, but I’ll keep it in my back pocket for the next time I feel a blog redesign coming on. It feels tidier and more-universal than my current approach, and I don’t think it’s an enormous sacrifice to lose the ability to hotlink directly to an open image in a post.

What do you think?

🕵️ Subscribing to DanQ.me's RSS feeds means that you'll get to see secret bonus posts not publicised on the main site. Clever you! 🧠

Articles – Dan Q

15 Aug 2025 at 14:23



Refresh complete

ReloadX
Home
(106) All feeds

Last 24 hours
Download OPML
A Very Good Blog by Keenan
*
A Working Library
Alastair Johnston
Anna Havron
Annie
Annie Mueller
Apple Annie's Weblog
*
Articles – Dan Q
*
Baty.net posts
bgfay
*
Bix Dot Blog
Brandon's Journal
Chris Coyier
Chris Lovie-Tyler
Chris McLeod's blog
*
Colin Devroe
*
Colin Walker – Daily Feed
Content on Kwon.nyc
Crazy Stupid Tech
*
daverupert.com
Dino's Journal 📖
dispatches
dominikhofer dot me
*
Dragoncatcher the blog
Excursions
*
Flashing Palely in the Margins
Floating Flinders
For You
*
Frank Meeuwsen
frittiert.es
Hello! on Alan Ralph
Human Stuff from Lisa Olivera
*
inessential.com
*
jabel
Jake LaCaze
*
James Van Dyne
*
Jan-Lukas Else
*
Jim Nielsen's Blog
Jo's Blog
*
Kev Quirk
lili's musings
Live & Learn
Lucy Bellwood
Maggie Appleton
*
Manton Reece
*
Manu's Feed
Matt's Blog
maya.land
*
Meadow
Minutes to Midnight RSS feed
Nicky's Blog
Notes – Dan Q
On my Om
Own Your Web
Paul's Dev Notes
*
QC RSS
rebeccatoh.co
reverie v. reality
*
Rhoneisms
ribbonfarm
Robert Birming
*
Robert Birming
Robin Rendle
Robin Rendle
Sara Joy
*
Scripting News for email
Sentiers – Blog
*
Simon Collison | Articles & Stream
strandlines
Tangible Life
the dream machine
*
The Torment Nexus
*
thejaymo
theunderground.blog
Thoughtless Ramblings
tomcritchlow.com
*
Tracy Durnell
*
Winnie Lim
*
yours, tiramisu

About Reader


Reader is a public/private RSS & Atom feed reader.


The page is publicly available but all admin and post actions are gated behind login checks. Anyone is welcome to come and have a look at what feeds are listed — the posts visible will be everything within the last week and be unaffected by my read/unread status.


Reader currently updates every six hours.


Close

Search




x
Colin Walker Colin Walker colin@colinwalker.blog