Skip to main content

How to Create an Image Lightbox in Pure CSS

Gregory Schier Headshot Gregory Schier • 4 min read

Cascading Style Sheets (CSS) is the language used to describe the presentation of a web page, which is where it stops for most of us. However, CSS can also be used to for stateful components, in place of JavaScript.

Today, we'll demonstrate how to build an image lightbox in pure CSS and HTML, no JavaScript required.

See the Pen Pure CSS Lightbox by Gregory Schier (@gschier) on CodePen.

Here are the requirements for the lightbox:

  1. Must show lightbox when clicking thumbnail
  2. Must load image after lightbox is shown
  3. Must hide lighbox after clicking enlarged image

Okay, let's build it!

The :target Selector#

The stateful nature of this implementation comes from the :target selector. It's what allows us to keep the lightbox visible after the click has ended.

The target selector can be used in CSS to style elements like this.

CSS Snippet
img:target {
  border: 5px solid red;
}

The selector becomes active when the img element contains an id attribute equal to the URL fragment (eg. https://codesalad.dev/#some-id).

HTML Snippet
<!-- Will have red background if the URL hash is #some-id -->
<img src="https://picsum.photos/seed/9/300/150" id="some-id" />

The lightbox takes advantage of this by doing the following:

  1. Include <img> thumbnail on page
  2. Wrap thumbnail in link <a href="#some-hash">...</a>
  3. Include hidden lightbox below thumbnail with id=some-hash
  4. Use CSS to show lightbox when it is the :target
  5. Wrap lightbox in <a href="#_"> to unset the target on click

NOTE: We use #_ instead of # to unset the URL hash because browsers will interpret # as an instruction to scroll to the top of the document.

Building The Lightbox#

So, here's what the HTML will look like for our lightbox. We'll need to add both the thumbnail and lightbox to make it work. When adding multiple lightboxes, ensure they use different id attributes.

HTML Snippet
<!-- Lightbox thumbnail, visible on page at all times -->
<a href="#some-id">
  <img src="https://picsum.photos/seed/9/300/150">
</a>

<!-- Include lightbox (position on page doesn't matter) -->
<a href="#" class="lightbox" id="some-id">
  <div style="background-image:url('https://picsum.photos/seed/9/900/450')"></div>
</a>

And here's the CSS to go along with it. I added some comments to explain what's going on.

CSS Snippet
.lightbox {
  /* Default to hidden */
  display: none;

  /* Overlay entire screen */
  position: fixed;
  z-index: 999;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;

  /* A bit of padding around image */
  padding: 1em;

  /* Translucent background */
  background: rgba(0, 0, 0, 0.8);
}

/* Unhide the lightbox when it's the target */
.lightbox:target {
  display: block;
}

.lightbox span {
  /* Full width and height */
  display: block;
  width: 100%;
  height: 100%;

  /* Size and position background image */
  background-position: center;
  background-repeat: no-repeat;
  background-size: contain;
}

Wrap-up#

That's all it takes to create a stateful lightbox in pure CSS. Here's the full working example, included below. Be sure to observe how the URL changes when showing and hiding the lightbox.

I hope that was helpful in showcasing some of CSS's lesser-known uses. Note that this implementation was meant for learning purposes and isn't recommended for production use, mostly for accessibility reasons.


Awesome, thanks for the feedback! 🤗

How did you like the article?