PhotoSwipe

repository·master·Indexed 12 days ago

https://github.com/dimsemenov/PhotoSwipe

A lightweight, flexible JavaScript image gallery and lightbox library providing a high-performance, touch-friendly, and responsive interface. Version 5.4.4 includes features for configuring zoom levels (initial, secondary, and max) and a UI API via pswp.ui.registerElement() to add custom buttons, HTML indicators, and navigation elements.

Tokens
25.5K
Snippets
68
Records
84
Agent score
98%

What's inside PhotoSwipe

  1. Dynamically add or remove slides

    master

    You can modify the slides in a running PhotoSwipe instance by manipulating pswp.options.dataSource.

    • If initialized from DOM elements, dataSource contains a gallery element and an items array of child elements.
    • If initialized from an array, dataSource is the array itself.

    Crucial Step: If you modify a slide that is currently active (the current, next, or previous slide), you MUST call pswp.refreshSlideContent(slideIndex) to reload that specific slide with the new data.

    // Example: Replacing the current slide's data
    pswp.options.dataSource[pswp.currSlide.index] = {
      src: 'new-image.jpg', 
      width: 800, 
      height: 600
    };
    pswp.refreshSlideContent(pswp.currSlide.index);
    
    // Example: Adding a new slide to the end
    pswp.options.dataSource.push({
      src: 'added-image.jpg', 
      width: 800, 
      height: 600
    });
    pswp.refreshSlideContent(pswp.getNumItems() - 1);
  2. Support custom content types using filters and events

    master

    By default, PhotoSwipe supports image and html content types. To support new types (like WebP <picture> elements or <iframe> embeds), you must use the addFilter method to extract custom data and event listeners to override the default rendering behavior.

    Key lifecycle events for custom content:

    • contentLoad: Use this to define the content element (e.g., creating a <div> or <picture> instead of the default <img>). Call e.preventDefault() to stop PhotoSwipe from using its default logic.
    • contentAppend: Use this to manually append your custom element to the slide container.
    • contentRemove: Use this to clean up your custom elements when navigating away from a slide.

    Note: PhotoSwipe is optimized for photos. Interactive content like iframes may have issues with swiping gestures. Always provide an outbound link as a fallback.

  3. How PhotoSwipe filters work

    master
    Filters in PhotoSwipe allow you to intercept and modify data or elements used by the lightbox. Every filter function must return the modified value (or the original value if no changes are made) to ensure the lightbox can continue its operations. Filters are registered using the lightbox.addFilter(name, callback) method.
  4. Required HTML markup for PhotoSwipe

    master

    To work with PhotoSwipe, your HTML elements (usually <a> tags) must include specific data attributes.

    Required Attributes

    • href or data-pswp-src: The URL of the large image. data-pswp-src has higher priority.
    • data-pswp-width: The width of the image.
    • data-pswp-height: The height of the image.

    Optional Attributes

    • data-pswp-srcset: Supports native srcset markup for responsive images.
    • data-cropped="true": Use this if the thumbnail image is cropped.
    • An <img> tag inside the link: Used as a thumbnail to be displayed before the large image loads (controlled by thumbSelector).
  5. Generate dynamic data with numItems and itemData filters

    master

    You can create a gallery with a large or infinite number of items without having them all in the DOM by using two specific filters:

    1. numItems: Overrides the total number of slides in the gallery.
    2. itemData: Triggered whenever PhotoSwipe requests data for a slide (usually before display or lazy-loading). Use this to return the src, width, and height for a specific index.

    This pattern is ideal for handling thousands of images efficiently.

    import PhotoSwipeLightbox from '/photoswipe/photoswipe-lightbox.esm.js';
    
    const lightbox = new PhotoSwipeLightbox({
      pswpModule: () => import('/photoswipe/photoswipe.esm.js'),
    });
    
    // Set total number of slides
    lightbox.addFilter('numItems', (numItems) => {
      return 1000;
    });
    
    // Provide data for each slide on demand
    lightbox.addFilter('itemData', (itemData, index) => {
      return {
        src: 'https://dummyimage.com/100x100/555/fff/?text=' + (index + 1),
        width: 100,
        height: 100
      };
    });
    
    lightbox.init();
  6. Browser support and fallbacks

    master

    PhotoSwipe is designed for modern browsers that support ES6 modules.

    • Unsupported Browsers: It may not work in IE11, Opera Mini, UC browser, or older versions of Chrome, Safari, and Firefox.
    • Progressive Enhancement: To ensure accessibility in unsupported browsers, always provide an alternative way to view the content (e.g., a direct link to the image). If you use the recommended markup (a link to the image), users in unsupported browsers can still access the large image via the link.
    • Fallback Implementation: You can provide a fallback using <script type="nomodule"></script>.
  7. How to bind events to PhotoSwipeLightbox

    master

    All PhotoSwipe events can be bound directly to the PhotoSwipeLightbox instance using the .on(eventName, callback) method. When the lightbox is open, these events are automatically mapped to the PhotoSwipe core. This allows you to manage lifecycle, animations, and content loading from the lightbox instance.

    const lightbox = new PhotoSwipeLightbox({
      // options...
    });
    lightbox.on('eventName', (eventData) => {
      // handle event
    });
    lightbox.init();
  8. Customize the loading indicator (preloader)

    master

    The loading indicator (a spinning 3/4 circle in the top left) appears only if an image fails to load within a specific timeframe (default is 2 seconds, adjustable via preloaderDelay).

    To style the preloader, use CSS to target the .pswp__icn class.

    Debugging Tip: To see the preloader permanently for testing/debugging, you can force its opacity via CSS using a custom mainClass.

    // Debugging: permanently display preloader
    const lightbox = new PhotoSwipeLightbox({
      gallery: '#gallery--perma-preloader',
      children: 'a',
      pswpModule: () => import('/photoswipe/photoswipe.esm.js'),
      mainClass: 'pswp-with-perma-preloader',
    });
    lightbox.init();
    /* debug: permanently display preloader */
    .pswp-with-perma-preloader .pswp__icn {
      opacity: 0.85 !important;
    }
  9. Run the PhotoSwipe demo website in development mode

    master

    To run the documentation and demo website with automatic rebuilding (watch mode) during development, follow these two steps:

    1. Install dependencies for the demo website:
      cd demo-docs-website
      npm install
    2. Start the watch process from the root directory:
      npm run watch
    # Step 1: In demo-docs-website/
    npm install
    
    # Step 2: In root/
    npm run watch
  10. Initialize PhotoSwipe from an Array of data

    master

    You can bypass the DOM-based gallery approach by passing an array of objects to the dataSource option. This is useful for purely programmatic galleries.

    Each object in the array should represent a slide. For image slides, include:

    • src: Image URL
    • width: Image width
    • height: Image height
    • srcset: (Optional) Responsive image set
    • alt: (Optional) Alt text
    • html: (Optional) Use this instead of src to render a custom HTML slide.

    To use the core PhotoSwipe without the Lightbox module, instantiate PhotoSwipe directly and call .init().

    import PhotoSwipe from '/photoswipe/photoswipe.esm.js';
    
    const options = {
      dataSource: [
        {
          src: 'https://dummyimage.com/1620x1080/555/fff/?text=1620x1080',
          width: 1620,
          height: 1080,
          alt: 'test image 1'
        },
        {
          html: '<div class="custom-html-slide">Custom HTML content</div>'
        }
      ],
      index: 0 // defines start slide index
    };
    
    const pswp = new PhotoSwipe(options);
    pswp.init();