Because Gridzy.js is very cautious and flexible, it can be combined with many many lightboxes. PhotoSwipe is one of the most responsive and performant lightbox scripts. Let’s combine them! 😉
Start with Gridzy.js
1. Upload the Gridzy files to your server and add them to your website (usually in the head section):
<link rel="stylesheet" href="gridzy/gridzy-2.0.min.css" />
<script src="gridzy/gridzy-2.0.min.js"></script>
2. Add the HTML code (anywhere in the body section):
<div class="gridzy">
<a href="path-to-image-1-big.jpg" data-size="1920x1080">
<img class="gridzyImage" src="path-to-image-1-small.jpg" alt="a random image" />
</a>
<a href="path-to-image-2-big.jpg" data-size="1920x1080">
<img class="gridzyImage" src="path-to-image-2-small.jpg" alt="another random image" />
</a>
<a href="path-to-image-3-big.jpg" data-size="1920x1080">
<img class="gridzyImage" src="path-to-image-3-small.jpg" alt="yet another random image" />
</a>
<a href="path-to-image-4-big.jpg" data-size="1920x1080">
<img class="gridzyImage" src="path-to-image-4-small.jpg" alt="a random image again" />
</a>
<a href="path-to-image-5-big.jpg" data-size="1920x1080">
<img class="gridzyImage" src="path-to-image-5-small.jpg" alt="one last random image" />
</a>
</div>
As you can see, the images are encapsulated in a
-tags. Additionally you need to consider these things:
- The
href
attribute should contain the URL to the large image. - The
data-size
attribute should contain the original size of the large image. - The CSS class
gridzyImage
is needed for allimg
tags. - The
src
attribute should contain the URL to the small image.
Then add PhotoSwipe
First you need to download PhotoSwipe from GitHub. Just unpack the ZIP archive and copy the “dist” folder into your project. You can rename the folder from “dist” to “photoswipe” for example, so you can’t get confused about this folder.
Step 1: include JS and CSS files
Add the following to your website (usually in the head section):
<link rel="stylesheet" href="photoswipe/photoswipe.css">
<link rel="stylesheet" href="photoswipe/default-skin/default-skin.css">
<script src="photoswipe/photoswipe.min.js"></script>
<script src="photoswipe/photoswipe-ui-default.min.js"></script>
Step 2: add PhotoSwipe HTML
Add the following directly before the closing </body>
:
<!-- Root element of PhotoSwipe. Must have class pswp. -->
<div class="pswp" tabindex="-1" role="dialog" aria-hidden="true">
<!-- Background of PhotoSwipe.
It's a separate element as animating opacity is faster than rgba(). -->
<div class="pswp__bg"></div>
<!-- Slides wrapper with overflow:hidden. -->
<div class="pswp__scroll-wrap">
<!-- Container that holds slides.
PhotoSwipe keeps only 3 of them in the DOM to save memory.
Don't modify these 3 pswp__item elements, data is added later on. -->
<div class="pswp__container">
<div class="pswp__item"></div>
<div class="pswp__item"></div>
<div class="pswp__item"></div>
</div>
<!-- Default (PhotoSwipeUI_Default) interface on top of sliding area. Can be changed. -->
<div class="pswp__ui pswp__ui--hidden">
<div class="pswp__top-bar">
<!-- Controls are self-explanatory. Order can be changed. -->
<div class="pswp__counter"></div>
<button class="pswp__button pswp__button--close" title="Close (Esc)"></button>
<button class="pswp__button pswp__button--share" title="Share"></button>
<button class="pswp__button pswp__button--fs" title="Toggle fullscreen"></button>
<button class="pswp__button pswp__button--zoom" title="Zoom in/out"></button>
<!-- Preloader demo https://codepen.io/dimsemenov/pen/yyBWoR -->
<!-- element will get class pswp__preloader--active when preloader is running -->
<div class="pswp__preloader">
<div class="pswp__preloader__icn">
<div class="pswp__preloader__cut">
<div class="pswp__preloader__donut"></div>
</div>
</div>
</div>
</div>
<div class="pswp__share-modal pswp__share-modal--hidden pswp__single-tap">
<div class="pswp__share-tooltip"></div>
</div>
<button class="pswp__button pswp__button--arrow--left" title="Previous (arrow left)">
</button>
<button class="pswp__button pswp__button--arrow--right" title="Next (arrow right)">
</button>
<div class="pswp__caption">
<div class="pswp__caption__center"></div>
</div>
</div>
</div>
</div>
Step 3: initialize
Add the following also directly before the closing </body>
(so, between the HTML, you just added, and the closing </body>
):
<script>
document.addEventListener('DOMContentLoaded', function() {
// Polyfills start
if (!Element.prototype.matches) Element.prototype.matches = Element.prototype.msMatchesSelector || Element.prototype.webkitMatchesSelector;
if (!Element.prototype.closest) { Element.prototype.closest = function(s) { var el = this;
do { if (el.matches(s)) return el; el = el.parentElement || el.parentNode; } while (el !== null && el.nodeType === 1); return null; }; }
// Polyfills end
// get PhotoSwipe element
var pswpElement = document.querySelectorAll('.pswp')[0];
// add click event listener
document.body.addEventListener('click', function(event) {
var alias = event.target ? event.target.closest('.gridzy a') : null;
if (alias) {
event.preventDefault();
openPhotoSwipe(alias.closest('.gridzy'), alias);
}
});
// open picture from URL if directly requested
setTimeout(function() {
var hash = location.hash.substring(1).split('&').map(function(val) { return val.split('='); });
var pos = hash.length, param = {}, gridzyElement, itemElement;
while (pos--) {
param[hash[pos][0]] = hash[pos][1];
}
if ('gid' in param && 'pid' in param) {
gridzyElement = document.querySelector((param.gid.match(/^[0-9]+$/) ? '' : '#' + param.gid + '.gridzy, ') + '.gridzy[data-gridzyid="' + param.gid + '"]');
itemElement = gridzyElement.querySelector((param.pid.match(/^[0-9]+$/) ? '' : '#' + param.pid + '.gridzyItem, ') + '.gridzyItem[data-gridzyitemid="' + param.pid + '"]');
openPhotoSwipe(gridzyElement, itemElement);
}
}, 0);
// initialize and open PhotoSwipe
function openPhotoSwipe(gridzyElement, itemElement) {
var itemElements = gridzyElement.children;
var pos = itemElements.length;
var items = [], img, size, title, startImg, thumbnails = [], options, gallery;
// prepare items
while (pos--) {
if (itemElements[pos].classList.contains('gridzyItemHidden')) {
continue;
}
img = itemElements[pos].querySelector('img.gridzyImage');
if (size = itemElements[pos].getAttribute('data-size')) {
size = itemElements[pos].getAttribute('data-size').split('x');
title = itemElements[pos].getAttribute('data-title');
title = title ? title : ((title = itemElements[pos].querySelector('.gridzyCaption')) ? title.innerText : '');
items.unshift({
src: itemElements[pos].href,
w: parseInt(size[0], 10),
h: parseInt(size[1], 10),
msrc: img.src,
title: title,
pid: itemElements[pos].hasAttribute('id') ? itemElements[pos].id : itemElements[pos].getAttribute('data-gridzyitemid')
});
thumbnails.unshift(img);
if (itemElement === itemElements[pos]) {
startImg = img;
}
}
}
// prepare options
options = {
index: thumbnails.indexOf(startImg) || 0,
galleryUID: (gridzyElement.hasAttribute('id') ? gridzyElement.id : gridzyElement.gridzy.id),
getThumbBoundsFn: function(index) {
var pageYScroll = window.pageYOffset || document.documentElement.scrollTop;
var rect = thumbnails[index].getBoundingClientRect();
return {x:rect.left, y:rect.top + pageYScroll, w:rect.width};
}
};
// open PhotoSwipe
gallery = new PhotoSwipe( pswpElement, PhotoSwipeUI_Default, items, options);
gallery.init();
}
});
</script>
That’s it!
The positions where to add the code snippets are only proposals. So, feel free to change the order and positions. You can also put the last code snippet into a JS file for example. The order of the snippets shouldn’t be relevant.
Have fun! ✌😊
Updates:
March 15, 2019
Changed the initialization code to only show images in the lightbox, that are not hidden by the Gridzy.js filter feature.
March 16, 2019
Fixed an issue in the initialization code. The start image (shown when opening the lightbox) wasn’t determined correctly anymore after yesterdays changes.
Hi Helmut,
Nice code, works well. Am trying to set the layout to ‘waterfall’, have added layout:’waterfall’ to options = {} but this doesn’t help. Is there a way to do this?
Thanks
Paul
Hi Paul,
thank you for your question! The options variable in this example are the options for PhotoSwipe. So for Gridzy you need to add it elsewhere.
Just add the attribute data-gridzy-layout=”waterfall” to the container div element. Like this:
<div class="gridzy" data-gridzy-layout="waterfall">
All the best,
Helmut
Hello Helmut,
This is an amazing combination and works like a charm. I love the action. Just wondering whether, there is a way to make the above work with srcset so we can serve bigger thumbnails to say 4k displays and smaller to mobiles.