Lightbox, with no JavaScript
Tags: css, webdev, frontend, lightbox
Published: 2020-07-17 19:22:51

I have been following the evolution of the Web since the 2000s and how things have changed. There are certain things that were only possible to do using JavaScript. Fortunately, today the scenario is different, and we have the luxury of being able to choose whether to use JS or not. One of these things is the effect called "lightbox".

### What it is

Lightbox is basically a fancier way to show an enlarged image, without leaving the page to see the entire photo, which is the default behavior of browsers. It usually comes in a frame that opens when clicking on the image, with a close button, to return to the previous view. It was created in 2012 by Lokesh Dakar, and it was a success. Soon followed by competing scripts, using other libraries or having other features. To this day, the Lokesh script works! I left the link to the original Lightbox website at the end of this article.

Nowadays, thanks to advances in CSS, it is possible to achieve the same effect, without the complication of using JavaScript. Below is a tutorial on how to implement one on your website.

### The code for the gallery

To achieve the effect, we need an HTML structure to have some example content:

```html
<section class="gallery">
  <h2>Gallery</h2>
  <div class="item">
    <a href="#image1">
      <img src="https://source.unsplash.com/fdlZBWIP0aM/500x500" />
    </a>
    <strong>Photo 1</strong>
  </div>
  <div class="item">
    <a href="#image2">
      <img src="https://source.unsplash.com/Yr4n8O_3UPc/500x500" />
    </a>
    <strong>Photo 3</strong>
  </div>
  <div class="item">
    <a href="#image3">
      <img src="https://source.unsplash.com/_-SwhhV7tSo/500x500" />
    </a>
    <strong>Photo 3</strong>
  </div>
</section>
```

In the code above, nothing new, just a section with three clickable images. Note that each anchor `<a>` has an `href="#imageN` where N is the image number. This will be important later on. The CSS for formatting the content goes below.

```css
@include (https://fonts.googleapis.com/css?family=Montserrat:300,300i,400,400i,700,700i&display=swap);

/* Body */
body {
  background: #111;
  box-sizing: border-box;
  color: #fff;
  font-family: "Montserrat", sans-serif;
  font-size: 12px;
  margin: 0;
  padding: 0;
}

a {
  text-decoration: none;
}

/* gallery */
.gallery {
  display: grid;
  grid-gap: 1em;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: 10vh auto;
  margin: 2em auto;
  max-width: 100%;
  width: 600px;
}

.gallery h2 {
  font-size: 30px;
  grid-column: 1/4;
}

.gallery a {
  cursor: zoom-in;
  transition: filter 0.2s ease-in-out;
}

.gallery a:hover {
  filter: brightness(90%);
}

.gallery .item strong {
  display: block;
  font-size: 1.5em;
  text-align: center;
}

.gallery img {
  border-radius: 1em;
  max-width: 100%;
}
```

I used `display: grid` in the `.gallery` section, but this is not part of the effect. I used it just for convenience. In a future article, I will write about how to use Grid Layout.

### The code for the lightboxes

HTML is also quite simple. Just create the following structure for each image that you want to have the enlargement effect:

```html
<div class="lightbox" id="imageN">
  <a href="#_" class="close">&times;</a>
  <div class="content">
    <img src="https://source.unsplash.com/fdlZBWIP0aM/900x900" />
    <p>Photo 1</p>
  </div>
</div>
```

In this code, we have a `<div>` with an `id` equivalent to the `href="# imageN"` present in the structure made for the gallery; a link with a generic anchor `href="#_"` to close the window; a `<div>` for the lightbox content; an 'img' with a higher resolution, to be the enlarged version and an optional caption.

Applying to the three images we have in the gallery, the code will look like this:

```html
<div class="lightboxes">
  <div class="lightbox" id="image1">
    <a href="#" class="close">&times;</a>
    <div class="content">
      <img src="https://source.unsplash.com/fdlZBWIP0aM/900x900" />
      <p>Photo 1</p>
    </div>
  </div>
  <div class="lightbox" id="image2">
    <a href="#" class="close">&times;</a>
    <div class="content">
      <img src="https://source.unsplash.com/Yr4n8O_3UPc/900x900" />
      <p>Photo 2</p>
    </div>
  </div>
  <div class="lightbox" id="image3">
    <a href="#" class="close">&times;</a>
    <div class="content">
      <img src="https://source.unsplash.com/_-SwhhV7tSo/900x900" />
      <p>Photo 3</p>
    </div>
  </div>
</div>
```

So far, nothing special. What really changes the game is what comes next.

```css
.lightbox {
  background: rgba(0, 0, 0, 0.8);
  display: none;
  position: fixed;
  z-index: 1000;
}

.lightbox:target {
  align-items: center;
  bottom: 0;
  display: flex;
  justify-content: center;
  left: 0;
  right: 0;
  top: 0;
}

.lightbox img {
  border-radius: 1em;
  display: block;
  margin: auto;
  max-height: 80vh;
  max-width: 90vh;
}

.lightbox .close {
  color: #fff;
  font-size: 4em;
  font-weight: bold;
  height: 1em;
  position: fixed;
  right: 0;
  top: 0;
  width: 1em;
  z-index: 1001;
}

.lightbox p {
  font-size: 2em;
  font-weight: bold;
  text-align: center;
}
```

Did you notice the pseudo-class `:target`? It does the trick!

Basically, it makes possible to change the style of the element that has its `id` at the end of the URL! Quite smart. If the id `#image1` is present in the browser address bar, the target will be reached, activating the effect applied in the rule that makes use of this feature.

The only limitation is if you want some extra functionality that is not possible in CSS, such as copying the image to the clipboard, integrating it with some application action or something very specific.

This technique does not need to be used only for this lightbox effect, of course. You can create modals, menus or other effects. Feel free to use your creativity. It is also not limited to enlarging images: any HTML element can be placed in the `<div>` element displayed after the click.

Use JavaScript only when necessary, otherwise, let CSS give you a little help. It's less logic to worry about.

I left a link below for the CodePen I did showcasing the effect with the code used in this article. Any questions or suggestions, leave a comment!

### Links

- [Code Pen for this article](https://codepen.io/elvessousa/pen/abOrYLK)
- [Original lightbox](https://www.lokeshdhakar.com/projects/lightbox2/)
- [This article, in Portuguese](https://blog.elvessousa.com.br/post/lightbox-sem-javascript)

---

If this article helped you in some way, consider [donating](https://www.buymeacoffee.com/elvessousa). This will help me to create more content like this!