Data Sources
From an Array (or NodeList)
Pass an array of any items via dataSource
option. Its length will determine amount of slides (which may be modified further from numItems event).
Each item should contain data that you need to generate slide (for image slide it would be src
(image URL), w
(width), h
height, srcset
, alt
).
If these properties are not present in your initial array, you may "pre-parse" each item from itemData event.
import PhotoSwipeLightbox from '/photoswipe/photoswipe-lightbox.esm.js';
const options = {
dataSource: [
// simple image
{
src: 'https://source.unsplash.com/Volo9FYUAzU/1620x1080',
w: 1620,
h: 1080,
alt: 'test image 1'
},
{
src: 'https://source.unsplash.com/RJzHlbKf6eY/1950x1300',
w: 1950,
h: 1300,
alt: 'test image 2'
},
// responsive image
{
srcset: 'https://dummyimage.com/1500x1000/555/fff/?text=1500x1000 1500w, https://dummyimage.com/1200x800/555/fff/?text=1200x800 1200w, https://dummyimage.com/600x400/555/fff/?text=600x400 600w',
src: 'https://dummyimage.com/1500x1000/555/fff/?text=1500x1000',
w: 1500,
h: 1000,
alt: 'test image 3',
},
// HTML slide
{
html: '<div class="custom-html-slide">This is custom HTML slide. <a href="http://example.com" target="_blank" rel="nofollow">Test Link</a>.</div>'
}
],
showHideAnimationType: 'none',
pswpModule: () => import('/photoswipe/photoswipe.esm.js')
};
const lightbox = new PhotoSwipeLightbox(options);
lightbox.init();
document.querySelector('#btn-open-pswp-from-arr').onclick = () => {
lightbox.loadAndOpen(0); // open the first image
};
.custom-html-slide {
font-size: 40px;
line-height: 45px;
max-width: 400px;
width: 100%;
padding: 0 20px;
margin: 50px auto 0;
color: #fff;
}
.custom-html-slide a {
color: #fff;
text-decoration: underline;
}
<button id="btn-open-pswp-from-arr" type="button">Open PhotoSwipe</button>
Custom last slide
To add a custom last slide increase the total number of slides by one using numItems
filter and make sure that correct itemData
is returned for the last slide.
import PhotoSwipeLightbox from '/photoswipe/photoswipe-lightbox.esm.js';
const options = {
gallery: '#gallery--custom-last-slide',
children: 'a',
pswpModule: () => import('/photoswipe/photoswipe.esm.js')
};
const lightbox = new PhotoSwipeLightbox(options);
lightbox.addFilter('numItems', (numItems) => {
numItems++;
return numItems;
});
lightbox.addFilter('itemData', (itemData, index) => {
if (index === lightbox.getNumItems() - 1) {
return {
html: '<div class="custom-html-slide">This is custom HTML slide. <a href="http://example.com" target="_blank" rel="nofollow">Link</a>.</div>',
};
}
return itemData;
});
lightbox.init();
<div class="pswp-gallery" id="gallery--custom-last-slide">
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-2500.jpg"
data-pswp-width="1875"
data-pswp-height="2500"
target="_blank">
<img src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-200.jpg" alt="" />
</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/2/img-2500.jpg"
data-pswp-width="1669"
data-pswp-height="2500"
target="_blank">
<img src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/2/img-200.jpg" alt="" />
</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/3/img-2500.jpg"
data-pswp-width="2500"
data-pswp-height="1666"
target="_blank">
<img src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/3/img-200.jpg" alt="" />
</a>
</div>
Dynamically generated data
The filter numItems
allows you to override the total number of slides. And itemData
will trigger every time PhotoSwipe requests data about the slide, which usually happens before slide is displayed or lazy-loaded.
The example below creates a gallery with 1000 images.
import PhotoSwipeLightbox from '/photoswipe/photoswipe-lightbox.esm.js';
const options = {
showHideAnimationType: 'none',
pswpModule: () => import('/photoswipe/photoswipe.esm.js'),
preload: [1,2]
};
const lightbox = new PhotoSwipeLightbox(options);
lightbox.addFilter('numItems', (numItems) => {
return 1000;
});
lightbox.addFilter('itemData', (itemData, index) => {
return {
src: 'https://dummyimage.com/100x100/555/fff/?text=' + (index + 1),
w: 100,
h: 100
};;
});
lightbox.init();
document.querySelector('#btn-open-pswp-dyn-gen').onclick = () => {
lightbox.loadAndOpen(0);
};
<button id="btn-open-pswp-dyn-gen" type="button">Open PhotoSwipe</button>
Custom HTML markup
You may completely override default requirements for HTML markup. In the example below we add thumbnail as background-image
, a custom attribute that stores image size, and make sure that zoom transition runs from <a>
rather than from <img>
within.
We also use domItemData
filter, instead of itemData
. It fires only once per each slide.
import PhotoSwipeLightbox from '/photoswipe/photoswipe-lightbox.esm.js';
const lightbox = new PhotoSwipeLightbox({
gallery: '#gallery--custom-html-markup',
children: 'a',
// Adjust thumbnail selector,
// (for opening/closing zoom transition)
thumbSelector: 'a',
pswpModule: () => import('/photoswipe/photoswipe.esm.js')
});
lightbox.addFilter('domItemData', (itemData, element, linkEl) => {
if (linkEl) {
const sizeAttr = linkEl.dataset.mySize;
itemData.src = linkEl.href;
itemData.w = Number(sizeAttr.split('x')[0]);
itemData.h = Number(sizeAttr.split('x')[1]);
itemData.msrc = linkEl.dataset.thumbSrc;
itemData.thumbCropped = true;
}
return itemData;
});
lightbox.init();
#gallery--custom-html-markup a {
width: 100px;
height: 100px;
background-size: cover;
background-position: 50% 50%;
text-indent: -300px;
overflow: hidden;
}
<div class="pswp-gallery pswp-gallery--single-column" id="gallery--custom-html-markup">
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-2500.jpg"
data-my-size="1875x2500"
data-thumb-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-200.jpg"
style="background-image:url(https://cdn.photoswipe.com/photoswipe-demo-images/photos/1/img-200.jpg)"
target="_blank">Test 1</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/2/img-2500.jpg"
data-my-size="1669x2500"
data-thumb-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/2/img-200.jpg"
style="background-image:url(https://cdn.photoswipe.com/photoswipe-demo-images/photos/2/img-200.jpg)"
target="_blank">Test 2</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/3/img-2500.jpg"
data-my-size="2500x1666"
data-thumb-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/3/img-200.jpg"
style="background-image:url(https://cdn.photoswipe.com/photoswipe-demo-images/photos/3/img-200.jpg)"
target="_blank">Test 3</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/4/img-2500.jpg"
data-my-size="2500x1667"
data-thumb-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/4/img-200.jpg"
style="background-image:url(https://cdn.photoswipe.com/photoswipe-demo-images/photos/4/img-200.jpg)"
target="_blank">Test 4</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/5/img-2500.jpg"
data-my-size="2500x1668"
data-thumb-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/5/img-200.jpg"
style="background-image:url(https://cdn.photoswipe.com/photoswipe-demo-images/photos/5/img-200.jpg)"
target="_blank">Test 5</a>
<a href="https://cdn.photoswipe.com/photoswipe-demo-images/photos/6/img-2500.jpg"
data-my-size="2500x1667"
data-thumb-src="https://cdn.photoswipe.com/photoswipe-demo-images/photos/6/img-200.jpg"
style="background-image:url(https://cdn.photoswipe.com/photoswipe-demo-images/photos/6/img-200.jpg)"
target="_blank">Test 6</a>
</div>
Separate DOM and data
If data is provided as array, but you still want to keep zoom animation. This is often the case when using some kind of dynamic image grid with paging or infinite scroll.
How-to:
- Pass array of images to
dataSource
option. - Use
thumbEl
filter to provide source of thumbnail element. PhotoSwipe will use its coordinates for animation. - Use
placeholderSrc
filter to provide the source of placeholder image. Alternatively, you may definemsrc
property in your data array. - Bind
click
event to gallery elements and call methodlightbox.loadAndOpen(3)
(where3
is image index in your array).
In the example below there are ten images in array, but only three are visible in DOM.
import PhotoSwipeLightbox from '/photoswipe/photoswipe-lightbox.esm.js';
const images = [
{ id: 1, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+1', w: 1500, h: 1000 },
{ id: 2, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+2', w: 1500, h: 1000 },
{ id: 3, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+3', w: 1500, h: 1000 },
{ id: 4, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+4', w: 1500, h: 1000 },
{ id: 5, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+5', w: 1500, h: 1000 },
{ id: 6, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+6', w: 1500, h: 1000 },
{ id: 7, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+7', w: 1500, h: 1000 },
{ id: 8, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+8', w: 1500, h: 1000 },
{ id: 9, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+9', w: 1500, h: 1000 },
{ id: 10, src: 'https://dummyimage.com/1500x1000/555/fff/?text=Image+10', w: 1500, h: 1000 },
];
const galleryEl = document.querySelector('#gallery--mixed-source');
const lightbox = new PhotoSwipeLightbox({
dataSource: images,
pswpModule: () => import('/photoswipe/photoswipe.esm.js')
});
lightbox.addFilter('thumbEl', (thumbEl, data, index) => {
const el = galleryEl.querySelector('[data-id="' + data.id + '"] img');
if (el) {
return el;
}
return thumbEl;
});
lightbox.addFilter('placeholderSrc', (placeholderSrc, slide) => {
const el = galleryEl.querySelector('[data-id="' + slide.data.id + '"] img');
if (el) {
return el.src;
}
return placeholderSrc;
});
lightbox.init();
// expose to use within onclick attribute
window.pswpLightbox = lightbox;
<div class="pswp-gallery" id="gallery--mixed-source">
<a onclick="pswpLightbox.loadAndOpen(2);return false;"
data-id="3"
href="https://dummyimage.com/1500x1000/555/fff/?text=Image+3"
target="_blank">
<img src="https://dummyimage.com/150x100/555/fff/?text=Thumb+3" alt="">
</a>
<a onclick="pswpLightbox.loadAndOpen(3);return false;"
data-id="4"
href="https://dummyimage.com/1500x1000/555/fff/?text=Image+4"
target="_blank">
<img src="https://dummyimage.com/150x100/555/fff/?text=Thumb+4" alt="">
</a>
<a onclick="pswpLightbox.loadAndOpen(4);return false;"
data-id="5"
href="https://dummyimage.com/1500x1000/555/fff/?text=Image+5"
target="_blank">
<img src="https://dummyimage.com/150x100/555/fff/?text=Thumb+5" alt="">
</a>
</div>