Lightbox

For this site I’ve built a simple lightbox to display images in the available viewport while dimming out the rest of the content. Click/tap on the photo below to see how it looks like:

Parking taxis in Kyoto
Photo taken from a series about Golden Hour in Kyoto

A fixed positioned image set to 100% width and height will ignore its aspect ratio, but using the CSS property object-fit takes care of this problem. Similar to background-size this property specifies how an image should be fitted into the bounding box established by its width and height. While contain works perfectly to fill the space in the best way, using scale-down makes sure the image won’t be displayed larger than its maximum size. Here is the CSS:

.lightbox-closed {
  cursor: zoom-in;
}

.lightbox-opened {
  background-color: #ffffff;
  z-index: 1;
  position: fixed;
  display: block;
  width: 100%;
  height: 100%;
  left: 0;
  top: 0;
  object-fit: scale-down;
  cursor: zoom-out;
  padding: 1rem;
}

On page load the class lightbox-closed is added to the image via JavaScript to change the cursor to zoom-in. Then each click toggles the class lightbox-opened to open/close the lightbox.

The padding adds some space between the image and the corners of the viewport. And instead of the white background color I am using a blurred version of the photo itself as background image. Browser support for object-fit is quite good, but I’d still add a check:

if (CSS.supports('object-fit', 'scale-down')) {
  Array.prototype.forEach.call(document.querySelectorAll('img'), function(element) {
    element.classList.add('lightbox-closed');
    element.addEventListener('click', function(event) {
      event.target.classList.toggle('lightbox-opened');
    });
  });
}

So if the browser does not support JavaScript or object-fit the lightbox functionality won’t be added.

Update: I’ve recently changed the approach a bit to take retina displays into account. To limit the image to its biggest possible size I am creating a bounding box with padding and then use contain for object-fit. I will write in detail about this soon.