Using PhotoSwipe v5 for Gallery Card

I was working on a custom Ghost theme for a customer and had some issues to make gallery card working with a lightbox. I checked official Source theme and noticed that it uses PhotoSwipe v4 with a bunch of custom code. I think new version of PhotoSwipe (v5) makes things easier and cleaner. It put the boilerplate template (pswp partial) automatically, it supports esm and it allows to customize gallery template (since standart HTML that Gallery card produces is not very nice for Photoswipe, because it doesn’t use <a> elements for image items).

So, here is my solution:

In default.hbs file, I put this part somewhere in <head> section:

    {{#is "post, page"}}
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/photoswipe@5.4.4/dist/photoswipe.min.css">
    {{/is}}

This just includes the required styles from CDN.

And I put the actual JS code to somewhere around {{ghost_foot}} in default.hbs as below:

{{#is "post, page"}}
    <script type="module">
        import PhotoSwipeLightbox from 'https://cdn.jsdelivr.net/npm/photoswipe@5.4.4/dist/photoswipe-lightbox.esm.min.js';
        import PhotoSwipeModule from 'https://cdn.jsdelivr.net/npm/photoswipe@5.4.4/dist/photoswipe.esm.min.js';

        const images = [...document.querySelectorAll('.kg-gallery-card img')];

        const lightbox = new PhotoSwipeLightbox({
            dataSource: images.map((el, index) => ({
                id: index,
                src: el.getAttribute('src'),
                msrc: el.getAttribute('src'),
                width: el.getAttribute('width'),
                height: el.getAttribute('height'),
                srcset: el.getAttribute('srcset')
            })),
            pswpModule: PhotoSwipeModule
        });

        images.forEach((el, index) => {
            el.addEventListener('click', () => {
                lightbox.loadAndOpen(index);
            })
        });

        lightbox.addFilter('thumbEl', (thumbEl, data, index) => {
            const el = images[index];
            if (el) {
                return el;
            }
            return thumbEl;
        });

        lightbox.init();
    </script>
{{/is}}

Here is running version: Herbarium

There are some improvements that I want to work further:

  • Move JS code to separate js file as an asset.
  • Make it work only if there is a gallery in the page.
  • Make it work on single images.
  • Test with responsive images

I wanted to share my solution before forgetting it. Any feedback is welcome!

1 Like