My solution ensures that:
- You can click an image and see a full-window popup dialog box containing a larger version of the image.
- The larger version of the image isn’t loaded until it’s needed.
- You can close the larger version with a close button. You can also use your browser’s back button.
- You can click again to download the larger version/use your browser to zoom in further.
- You can share/bookmark etc. the URL of a zoomed-in image and the recipient will see the same image (and return to the image, in the right blog post, if they press the close button).
- No HTTP round trip is required when opening/closing a lightbox: it’s functionally-instantaneous.2
Here’s how it works –
For each lightboxed image in a post, a
<dialog> for that image is appended to the post. That dialog contains a larger copy of the image (set to
loading="lazy" so the browser have to download it until it’s needed), and a “close” button.
The image in the post contains an anchor link to the dialog; the close button in the dialog links back to the image in the post.3 I wrap the lightbox image itself in a link to the full version of the image, which makes it easier for users to zoom in further using their browser’s own tools, if they like.
Even without CSS, this works (albeit with “scrolling” up and down to the larger image). But the clever bit’s yet to come:
Lightboxes are hidden by default (
display: none), but configured to fill the window when shown.
They’re shown by the selector
.lightbox:target, which is triggered by the
id of the
<dialog> being referenced by the anchor part of
the URL in your address bar!
I’d also like to take a deeper dive into the accessibility implications of this approach: I think it’s pretty good, but accessibility is a big topic and there’s always more to learn.
I hope the idea’s of use to somebody else looking to achieve this kind of thing, too.