YurbaPV

YurbaPhotoViewer

Fullscreen image viewer with gallery support, navigation, zoom, rotate, download, captions, and customizable corner buttons.

Usage
<link rel="stylesheet" href="/dist/yurba-pv.min.css">
<script src="/dist/yurba-pv.min.js"></script>

Create a viewer with YurbaPV.create(). It appends itself to document.body and scans the document for elements with a data-ypv attribute automatically.

const viewer = YurbaPV.create()

Add photos in HTML — no extra JS needed for static content.

<a href="/photo-large.jpg" data-ypv="album" data-id="0" data-caption="Sunset">
    <img src="/photo-thumb.jpg">
</a>

Links added dynamically are bound manually with bind().

viewer.bind(document.querySelector('#my-link'))
Config

All options are passed to YurbaPV.create().

const viewer = YurbaPV.create({
    icons: {
        left:     '<span class="material-symbols-rounded">arrow_back</span>',
        right:    '<span class="material-symbols-rounded">arrow_forward</span>',
        zoom:     '<span class="material-symbols-rounded">search</span>',
        download: '<span class="material-symbols-rounded">download</span>',
        rotate:   '<span class="material-symbols-rounded">refresh</span>',
    },
    buttons: [
        {
            html: '<a class="y-pv__btn" id="delete"><span class="material-symbols-rounded">delete</span></a>',
            prepend: false,
            onClick: (viewer) => {
                viewer.removePhoto(viewer.getCurrentGallery(), viewer.getCurrentPhoto())
                viewer.close()
            }
        }
    ]
})
OptionTypeDescription
icons optional object Override built-in button icons. Keys: left, right, zoom, download, rotate. Each value is an HTML string.
controls optional object Show or hide individual built-in buttons. Keys: zoom, rotate, download. Set to false to hide. Default: all visible.
buttons optional array Custom buttons to add to the corner button row. Each item: { html, prepend?, onClick? }. Use the y-pv__btn class to match built-in styling. prepend inserts before the built-ins (default false). onClick(viewer, event) is called on click.
Data attributes
AttributeTypeDescription
data-ypv required string Gallery id. Links sharing the same id form one gallery and can be navigated with the arrows.
data-id required number Numeric position of the photo inside its gallery. Determines order and prev/next.
href / data-url required string Full-size image URL. href is used first, falling back to data-url.
data-caption optional string Caption shown over the image.

Live demo

Click a thumbnail to open the viewer. Use the arrows or ←/→ keys to navigate, the corner buttons to zoom, download or rotate, and Esc or the backdrop to close.


Controls

Built-in interactions — no configuration needed.

Keyboard & navigation
InputAction
/ or nav arrowsPrevious / next photo in the gallery.
Esc or backdrop clickClose the viewer.
Double-click imageZoom in (first click) / zoom out (second click).
Zoom & pan

Scroll the mouse wheel over the viewer to zoom in or out continuously (0.5× – 4×). The zoom button in the corner snaps between 1× and 2×.

When the image is zoomed in beyond the viewport size, click and drag to pan. The cursor changes to a grab hand when panning is available. Zooming back out to fit the screen resets the pan position automatically.

The caption is hidden while the image is zoomed in and reappears when zoom returns to 1×.

Auto-hide UI

The close button, navigation arrows, corner buttons, and caption fade out after 2 seconds of inactivity. Any mouse movement or click resets the timer and brings the UI back.


API

Methods on the <yurba-pv> element.

bind
viewer.bind(element, caption)
ParamTypeDescription
element required HTMLElement A link carrying the data attributes. Registers it into its gallery and opens the viewer on click.
caption optional string Fallback caption used when the element has no data-caption.

Elements already in the DOM with data-ypv are bound automatically — call bind() only for content added afterwards.

open / close
viewer.open()
viewer.close()

Show or hide the viewer with a fade. open() emits yurba-pv.open, close() emits yurba-pv.close. The viewer also closes on Esc or a backdrop click.

setPhoto
viewer.setPhoto(galleryId, photoId)

Displays a specific photo by gallery and numeric id, updating the caption and prev/next arrows. Called internally on click, but available for manual control.

removePhoto
viewer.removePhoto(galleryId, photoId)

Removes a photo from a gallery. The gallery itself is dropped once empty.

clearGallery
viewer.clearGallery(galleryId)

Empties a gallery. Useful before re-binding a dynamic list of images.

Getters
MethodReturnsDescription
getCurrentElement() HTMLElement The link that opened the currently shown photo.
getCurrentGallery() string Id of the active gallery.
getCurrentPhoto() number Id of the active photo.

Events

Overview

Both events fire on the <yurba-pv> element and carry currentGallery and currentPhoto properties.

yurba-pv.open

Fired when the viewer opens.

viewer.addEventListener('yurba-pv.open', e => {
    console.log(e.currentGallery, e.currentPhoto)
})
yurba-pv.close

Fired when the viewer closes (button, backdrop, or Esc).

viewer.addEventListener('yurba-pv.close', () => {})

Customization

Control which built-in buttons are visible and add your own buttons to the corner button row.

Hiding controls

Pass a controls object to YurbaPV.create(). Each key corresponds to a built-in button — set it to false to hide it. Omitted keys default to visible.

const viewer = YurbaPV.create({
    controls: {
        zoom:     false,
        rotate:   false,
        download: false,
    }
})
KeyDefaultDescription
zoom true Toggle zoom button. When visible, clicking it zooms in; clicking again resets to 1×. Scroll wheel zoom is always available regardless of this setting.
rotate true Toggle rotate button. Each click rotates the image 90°.
download true Toggle download button. Fetches the full-size image and triggers a browser download.
Custom buttons

Add your own buttons to the corner button row via the buttons array. Each entry is an object with an html string and an optional prepend flag. Use the y-pv__btn class to match the built-in button style.

const viewer = YurbaPV.create({
    buttons: [
        {
            html: '<a class="y-pv__btn"><span class="material-symbols-rounded">share</span></a>',
            prepend: true,
            onClick: (viewer, e) => {
                console.log('share', viewer.getCurrentPhoto())
            }
        },
        {
            html: '<a class="y-pv__btn"><span class="material-symbols-rounded">delete</span></a>',
            onClick: (viewer) => {
                viewer.removePhoto(viewer.getCurrentGallery(), viewer.getCurrentPhoto())
                viewer.close()
            }
        }
    ]
})
KeyTypeDescription
html required string HTML markup inserted into the corner button row. Use the y-pv__btn class to match built-in styling.
onClick optional function Click handler. Receives (viewer, event)viewer is the <yurba-pv> element, event is the MouseEvent.
prepend optional boolean When true, inserts the button before the built-in buttons. Default: false (appends after).