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.
Demonstration
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.
Default
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.
Captions
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.
Google Map
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.
Jump Links
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:
Method 1: Using JavaScript Function
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.
Method 2: Using URL Hash
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)Implementation Details
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:
Responsive Design
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 Integration
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.
Captions and Accessibility
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.
Screen Reader Compatibility
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.
Performance Optimization
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.
Future Enhancements
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.
The Code
Base Files
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.
HTML
<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>
Custom CSS
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
}
JavaScript
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();
Special Thanks
This page is comprised of my own additions and either partially or heavily modified elements from the following source(s):