Learn the fundamentals of configuring VistaView for your image galleries.
The simplest way to use VistaView requires just two things: importing the library and specifying which elements to use.
The recommended approach uses anchor tags wrapping images:
<div id="gallery">
<a href="/images/photo1-full.jpg">
<img src="/images/photo1-thumb.jpg" alt="Photo 1" />
</a>
<a href="/images/photo2-full.jpg">
<img src="/images/photo2-thumb.jpg" alt="Photo 2" />
</a>
</div>
import { vistaView } from 'vistaview';
import 'vistaview/style.css';
vistaView({
elements: '#gallery a',
});
Benefits:
- Progressive loading from thumbnail to full-size
- Works without JavaScript
- SEO-friendly
You can also select images directly:
<div id="gallery">
<img src="/images/thumb1.jpg" data-vistaview-src="/images/full1.jpg" alt="Photo 1" />
<img src="/images/thumb2.jpg" data-vistaview-src="/images/full2.jpg" alt="Photo 2" />
</div>
vistaView({
elements: '#gallery img',
});
You can also pass an array of image configuration objects directly:
import type { VistaImgConfig } from 'vistaview';
const images: VistaImgConfig[] = [
{ src: '/images/photo1.jpg', alt: 'Photo 1' },
{ src: '/images/photo2.jpg', alt: 'Photo 2' },
{
src: '/images/photo3.jpg',
alt: 'Photo 3',
srcSet: '/images/photo3-800.jpg 800w, /images/photo3-1200.jpg 1200w',
},
];
vistaView({
elements: images,
});
VistaImgConfig Type:
interface VistaImgConfig {
src: string; // Full-size image URL (required)
alt?: string; // Alt text for the image
srcSet?: string; // Responsive image srcset attribute
}
Note: Thumbnails are not supported when using an array. This approach is best for programmatically generated galleries.
The vistaView function returns an instance with methods to control the lightbox programmatically:
const vista = vistaView({
elements: '#gallery a',
});
// Available methods:
vista.open(0); // Open lightbox at index 0
vista.close(); // Close the lightbox
vista.next(); // Navigate to next image
vista.prev(); // Navigate to previous image
vista.view(2); // Jump to image at index 2
vista.zoomIn(); // Zoom in
vista.zoomOut(); // Zoom out
vista.getCurrentIndex(); // Get current image index
vista.reset(); // Recalculate elements; for selectors: re-queries DOM and re-attaches click listeners; for arrays: updates element count only
vista.destroy(); // Clean up and remove lightbox
VistaInterface Type:
interface VistaInterface {
open: (startIndex?: number) => void; // Open at specific index
close: () => Promise<void>; // Close lightbox
reset: () => void; // For selectors: re-queries DOM & re-attaches click listeners; For arrays: updates count only
next: () => void; // Go to next image
prev: () => void; // Go to previous image
zoomIn: () => void; // Zoom in current image
zoomOut: () => void; // Zoom out current image
destroy: () => void; // Remove lightbox completely
getCurrentIndex: () => number; // Get current image index
view: (index: number) => void; // Navigate to specific index
}
When you need different lightbox configurations across different sections of your application, you have two main approaches:
Create separate VistaView instances for each gallery with different configurations:
// Product gallery with zoom enabled
const productGallery = vistaView({
elements: '#product-images a',
maxZoomLevel: 3,
arrowOnSmallScreens: true,
controls: {
topRight: ['zoomIn', 'zoomOut', 'close'],
},
});
// Portfolio gallery with minimal UI
const portfolioGallery = vistaView({
elements: '#portfolio a',
maxZoomLevel: 1, // No zoom
keyboardListeners: false,
controls: {
topRight: ['close'],
},
});
// Blog gallery with downloads
import { download } from 'vistaview/extensions/download';
const blogGallery = vistaView({
elements: '#blog-post img',
extensions: [download()],
});
Advantages:
- Each gallery is independent with its own configuration
- Different extensions per gallery
- No need to reconfigure or reset
- Straightforward and maintainable
Memory:
- Each instance maintains its own state and event listeners
- Automatically cleaned up when you call
destroy()
Use a single instance and update content dynamically. The approach differs based on whether you use selectors or arrays:
Update the DOM, then call reset() to re-query elements and re-attach listeners:
const vista = vistaView({
elements: '#dynamic-gallery a',
maxZoomLevel: 2,
});
// Example Async function to fetch and update gallery
async function updateGallery(category: string) {
const response = await fetch(`/api/images?category=${category}`);
const images = await response.json();
const gallery = document.querySelector('#dynamic-gallery');
// Update DOM
gallery.innerHTML = images
.map(
(img: { src: string; alt: string }) => `
<a href="${img.src}">
<img src="${img.src}" alt="${img.alt}" />
</a>
`
)
.join('');
// Re-query DOM and re-attach click listeners
vista.reset();
}
How reset() works with selectors:
- Re-queries the DOM using the original selector
- Updates
state.elmLength
- Removes and re-attaches click event listeners
- Images become clickable automatically
Mutate the array reference, then call reset() to update count:
// Create array that will be mutated
const currentImages: VistaImgConfig[] = [];
const vista = vistaView({
elements: currentImages, // Stores the array reference
maxZoomLevel: 2,
});
// Example Async function to fetch and update gallery
async function updateGallery(category: string) {
const response = await fetch(`/api/images?category=${category}`);
const images = await response.json();
// Mutate the original array (don't reassign!)
currentImages.length = 0;
currentImages.push(...images);
// Update element count
vista.reset();
}
How reset() works with arrays:
- Reads
this.elements.length to update count
- Does NOT attach click listeners (arrays have no DOM elements)
- You must call
open() programmatically
Advantages (both):
- Single instance reduces memory
- Good for SPAs with dynamic content
- All content shares same configuration
Limitations (both):
- Cannot change configuration after initialization
- All galleries share same settings (zoom, extensions, controls)
Always destroy instances when they’re no longer needed:
// Before page navigation in SPAs
function cleanup() {
productGallery.destroy();
portfolioGallery.destroy();
blogGallery.destroy();
}
// the following example in react and Vue
// is only needed if you are using
// hooks, composable, or creating and managing you own instance.
// In React - basic cleanup
useEffect(() => {
const vista = vistaView({ elements: '#gallery a' });
return () => vista.destroy();
}, []);
// In React - destroy and recreate when data changes
const [images, setImages] = useState<VistaImgConfig[]>([]);
useEffect(() => {
const vista = vistaView({
elements: images, // Works for both: arrays, or '#gallery a' when DOM re-renders
maxZoomLevel: 2,
});
return () => vista.destroy();
}, [images]);
// In Vue
onUnmounted(() => {
vista.destroy();
});