Table of Contents

Photo Gallery

Welcome to my photo gallery. This section showcases various images displayed using the PhotoSwipe library, providing a sleek and interactive browsing experience. Each image opens in a full-screen lightbox for a detailed view. Explore the different layouts and features below.

In this section, I demonstrate the capabilities of the PhotoSwipe gallery. You will see images arranged in different layouts and styles, highlighting how versatile and powerful this tool is. Whether it's a portfolio, product images, or other visual content, PhotoSwipe enhances the presentation.

This default gallery presents images in a responsive grid layout. Click on any image to open it in a full-screen lightbox. This approach ensures that your images look great on any device, from desktops to mobile phones.


This gallery includes captions for each image, providing additional context or information. Use the checkbox below to toggle the visibility of the captions. Captions can enhance the user experience by offering more details about each photo.

The last item has no caption.

Toggle Captions

In this example an interactive Google Map is inserted into the second slot of the gallery. Swipe gestures between the lightbox and Google Maps frame can interfere with each other in this implementation, for this reason either additional modifications or avoiding this approach is recommended in user-facing production environments. However, this currently serves as a strong demonstration of the flexibility of the PhotoSwipe codebase.


This section demonstrates the use of jump links within the gallery. Clicking the button below will directly open the second photo in the second gallery, showcasing the smooth navigation capabilities. There are two methods provided to achieve this:

Open Gallery 2, Item 2 (Function)

This method uses a custom JavaScript function PSWP_Open(gallery, item) to directly open the specified gallery item. This approach is cleaner and provides more control over the gallery behavior. It also has greater support for working even if the browser does not detect hash changes.

Advantages:

  • Directly opens the specified gallery item.
  • Provides more flexibility and control over the gallery behavior when nested with other code.
  • Ensures better compatibility across different browsers.

When the url hash changes, the lightbox will detect this and automatically attempt to open the gallery and item. Below is a button that will change the url hash as a demonstration of this capability.

Open Gallery 1, Item 3 (URL Hash)

The structure of this photo gallery has been carefully designed to provide a seamless user experience across various devices while ensuring accessibility and ease of use. Below are the key considerations and decisions made during the implementation:

By using a responsive grid layout, the gallery adapts to different screen sizes, ensuring that images are displayed appropriately on desktops, tablets, and mobile phones. The use of classes like col-default-12, col-phone-12, col-tablet-6, and col-desktop-small-4 ensures a flexible grid system that adjusts based on the device's viewport.

PhotoSwipe is a powerful library that provides a full-screen lightbox effect for images. Integrating PhotoSwipe enhances the user experience by allowing users to view images in greater detail. The lightbox setup is initialized with specific gallery and item selectors to ensure that the right elements are targeted for the lightbox effect.

Including captions for images provides additional context and information, enhancing the overall user experience. The figcaption element is used to semantically associate the caption with the image, which is beneficial for screen readers and improves accessibility. The checkbox for the Captions gallery demonstrates that captions can be hidden until the user enlarges an image or is using a screen reader. This feature ensures a cleaner interface while still providing necessary information when needed.

Accessibility is a crucial aspect of web design. The gallery structure ensures compatibility with screen readers by using semantic HTML elements like figure and figcaption. The alt attributes in the img tags provide descriptive text for screen readers, making the gallery accessible to visually impaired users. The dynamic caption feature in the PhotoSwipe lightbox further enhances accessibility by updating the caption content based on the current slide.

To ensure optimal performance, external stylesheets and scripts are loaded only when necessary. This minimizes the initial load time and improves the overall performance of the gallery. Additionally, the use of smaller placeholder images for thumbnails and larger images for the lightbox view balances image quality with loading speed.

The current implementation provides a solid foundation for a photo gallery. Future enhancements could include additional features such as image filtering, sorting options, and lazy loading for improved performance. These enhancements would further refine the user experience and make the gallery even more versatile and user-friendly.

All base files can be found at https://photoswipe.com/. The files I used were photoswipe.css, photoswipe.umd.min.js, and photoswipe-lightbox.umd.min.js. I load them in that order, with the CSS in the head of the webpage and the JavaScript at the end of the webpage.

<h3>Default</h3>

<div class="pswp-gallery row row--auto-clear" id="pswp-gallery-default">
  <a class="col-default-12 col-phone-6 col-tablet-4 col-desktop-small-3" href="https://dummyimage.com/1200x600/422/fff" data-pswp-width="1200" data-pswp-height="600">
    <img src="https://dummyimage.com/120x60/422/fff" alt="" />
  </a>
  <a class="col-default-12 col-phone-6 col-tablet-4 col-desktop-small-3" href="https://dummyimage.com/1200x1200/242/fff" data-pswp-width="1200" data-pswp-height="1200">
    <img src="https://dummyimage.com/60x60/242/fff" alt="" />
  </a>
  <a class="col-default-12 col-phone-6 col-tablet-4 col-desktop-small-3" href="https://dummyimage.com/600x1200/224/fff" data-pswp-width="600" data-pswp-height="1200">
    <img src="https://dummyimage.com/30x60/224/fff" alt="" />
  </a>
</div>

<h3>Captions</h3>

<div class="pswp-gallery row row--auto-clear" id="pswp-gallery-caption">
  <figure class="col-default-12 col-phone-6 col-tablet-4 col-desktop-small-3">
    <a class="pswp-gallery__item" href="https://dummyimage.com/1200x600/422/fff" data-pswp-width="1200" data-pswp-height="600">
      <img src="https://dummyimage.com/120x60/422/fff" alt="" />
    </a>
    <figcaption>A wide image with a <a class="button button--small" href="" onclick="return false;">button</a></figcaption>
  </figure>

  <figure class="col-default-12 col-phone-6 col-tablet-4 col-desktop-small-3">
    <a class="pswp-gallery__item" href="https://dummyimage.com/1200x1200/242/fff" data-pswp-width="1200" data-pswp-height="1200">
      <img src="https://dummyimage.com/60x60/242/fff" alt="" />
    </a>
    <figcaption>A square image.</figcaption>
  </figure>

  <figure class="col-default-12 col-phone-6 col-tablet-4 col-desktop-small-3">
    <a class="pswp-gallery__item" href="https://dummyimage.com/600x1200/224/fff" data-pswp-width="600" data-pswp-height="1200">
      <img src="https://dummyimage.com/30x60/224/fff" alt="" />
    </a>
    <figcaption>A tall image.</figcaption>
  </figure>
</div>

The below CSS is what I used to get PhotoSwipe to work with my site.

[class^=pswp],
[class*=pswp] {
  font-family: "Helvetica Neue", Helvetica, Arial, sans-serif !important;
  font-size: inherit !important
}

.pswp__container {
  margin: 0px !important
}

.pswp__top-bar {
  padding: 0px;
  margin: 0px !important
}

.pswp svg {
  pointer-events: none;
  cursor: pointer
}

.pswp svg use {
  pointer-events: none;
  cursor: pointer
}

.pswp__button {
  background: rgba(127, 127, 127, .3725490196) !important;
  border-radius: .25em;
  margin: 8px;
  padding: 8px;
  height: 50px
}

.pswp__icn {
  top: 9px
}

.pswp__button,
.pswp__button:link,
.pswp__button:visited,
.pswp__button:hover,
.pswp__button:focus,
.pswp__button:active {
  -webkit-box-shadow: 0 4px 2px rgba(0, 0, 0, .15);
  box-shadow: 0 4px 2px rgba(0, 0, 0, .15)
}

.pswp__button--arrow {
  top: calc(50% - 48px);
  width: 60px;
  height: 80px;
  position: absolute !important
}

.pswp__button--arrow--prev .pswp__icn {
  left: 8px
}

.pswp__button--arrow--next .pswp__icn {
  right: 8px
}

.pswp__preloader {
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
  transform: translate(-50%, -50%);
  pointer-events: none;
  width: 128px;
  height: 128px;
  opacity: .625
}

.pswp__preloader .pswp__icn {
  -webkit-animation: none !important;
  animation: none !important;
  background-image: url("/image/interface/animation/busy/001_light_128px.gif");
  width: 128px;
  height: 128px;
  top: 0;
  left: 0
}

.pswp__preloader .pswp__icn path {
  display: none !important
}

.pswp__counter {
  margin-right: auto
}

.pswp__top-bar {
  height: 100%
}

.pswp__custom-caption {
  background: rgba(34, 34, 34, .4980392157);
  color: #fff;
  font-size: 1rem;
  line-height: 1;
  padding: 16px;
  border-radius: 4px;
  width: calc(100% - 16px);
  max-width: 400px;
  position: absolute;
  left: 50%;
  bottom: 8px;
  -webkit-transform: translateX(-50%);
  transform: translateX(-50%);
  text-align: center
}

.pswp__zoom-level-indicator {
  background: rgba(34, 34, 34, .4980392157);
  color: #fff;
  font-size: 1rem;
  line-height: 18px;
  padding: 16px;
  border-radius: 4px;
  margin: 8px;
  height: 50px
}

Here is the JavaScript used to initialize the above galleries with PhotoSwipe lightbox.

var lightbox = new PhotoSwipeLightbox({
  gallery: '#pswp-gallery-default',
  children: 'a',
  // dynamic import is not supported in UMD version
  pswpModule: PhotoSwipe
  // history: true
});
lightbox.on('uiRegister', function() {
  lightbox.pswp.ui.registerElement({
    name: 'zoom-level-indicator',
    order: 9,
    onInit: (el, pswp) => {
      pswp.on('zoomPanUpdate', (e) => {
        if (e.slide === pswp.currSlide) {
          el.innerText = 'Zoom: ' + Math.round(pswp.currSlide.currZoomLevel * 100) + '%';
        }
      });
    }
  });
});
lightbox.init();

var lightbox_captions = new PhotoSwipeLightbox({
  gallery: '#pswp-gallery-caption',
  children: '.pswp-gallery__item',
  // dynamic import is not supported in UMD version
  pswpModule: PhotoSwipe
  // history: true
});
lightbox_captions.on('uiRegister', function() {
  lightbox_captions.pswp.ui.registerElement({
    name: 'zoom-level-indicator',
    order: 9,
    onInit: (el, pswp) => {
      pswp.on('zoomPanUpdate', (e) => {
        if (e.slide === pswp.currSlide) {
          el.innerText = 'Zoom: ' + Math.round(pswp.currSlide.currZoomLevel * 100) + '%';
        }
      });
    }
  });
});
lightbox_captions.on('uiRegister', function() {
  lightbox_captions.pswp.ui.registerElement({
    name: 'custom-caption',
    order: 9,
    isButton: false,
    appendTo: 'root',
    html: 'Caption text',
    onInit: (el, pswp) => {
      lightbox_captions.pswp.on('change', () => {
        const currSlideElement = lightbox_captions.pswp.currSlide.data.element;
        let captionHTML = '';
        if (currSlideElement) {
          const captionElement = currSlideElement.parentElement.querySelector('figcaption');
          if (captionElement) {
            // get caption from figcaption element
            captionHTML = captionElement.innerHTML;
          } else {
            // get caption from alt attribute
            captionHTML = currSlideElement.querySelector('img').getAttribute('alt');
          }
        }
        if (captionHTML) {
          el.innerHTML = captionHTML;
          el.style.display = 'block';
        } else {
          el.style.display = 'none';
        }
      });
    }
  });
});
lightbox_captions.init();

This page is comprised of my own additions and either partially or heavily modified elements from the following source(s):