Media Lightbox

Lightbox

A fully declarative lightbox. Add data-wf-lightbox to any trigger element and the JS handles the rest — no markup beyond the trigger is required. Supports images , native video ( .mp4 / .webm ), YouTube , Vimeo , and iframes . The media type is detected automatically from the URL; use data-wf-type to force it.

Basic

Import the module once. All [data-wf-lightbox] triggers are wired automatically on DOMContentLoaded .

JS
import './wf-lightbox.js'
HTML
<!-- Image: src comes from href -->
<a href="photo-full.jpg" data-wf-lightbox data-wf-caption="Forest trail">
  <img src="photo-thumb.jpg" alt="Forest trail">
</a>

<!-- Image: src explicit (for non-<a> triggers) -->
<button data-wf-lightbox data-wf-src="photo-full.jpg" data-wf-type="image">
  View photo
</button>

Native Video

URLs ending in .mp4 , .webm , or .ogg are detected automatically as native video. The video element gets controls , autoplay , and playsinline . Set data-wf-type="video" explicitly if the URL has no recognizable extension (e.g., a signed CDN URL).

HTML
<!-- Auto-detected from .mp4 extension -->
<a href="demo.mp4" data-wf-lightbox data-wf-caption="Product demo">
  Watch demo
</a>

<!-- Forced type (signed CDN URL without extension) -->
<a href="https://cdn.example.com/video?token=xyz"
   data-wf-lightbox data-wf-type="video">
  Watch video
</a>

YouTube

YouTube URLs are auto-detected. Short ( youtu.be/ ), full ( youtube.com/watch?v= ), and embed ( youtube.com/embed/ ) formats all work. The video ID is extracted and the player is embedded via the YouTube iframe API with autoplay=1 .

HTML
<!-- Short URL -->
<a href="https://youtu.be/dQw4w9WgXcQ" data-wf-lightbox>Watch</a>

<!-- Full URL -->
<a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ" data-wf-lightbox>Watch</a>

<!-- Embed URL -->
<a href="https://www.youtube.com/embed/dQw4w9WgXcQ" data-wf-lightbox>Watch</a>

Vimeo

Vimeo URLs ( vimeo.com/<id> or vimeo.com/video/<id> ) are auto-detected. The video ID is extracted and the player is embedded via the Vimeo iframe API with autoplay=1 .

HTML
<!-- Standard Vimeo URL -->
<a href="https://vimeo.com/123456789" data-wf-lightbox>Watch</a>

<!-- /video/ form also works -->
<a href="https://vimeo.com/video/123456789" data-wf-lightbox>Watch</a>

Iframe

Set data-wf-type="iframe" to load any URL in an embedded frame. The default frame is min(92vw, 1000px) wide and min(80dvh, 660px) tall. Override with data-wf-width and data-wf-height (values in px, no unit suffix needed).

HTML
<!-- Default iframe size -->
<a href="https://example.com/preview"
   data-wf-lightbox data-wf-type="iframe">
  Open preview
</a>

<!-- Custom dimensions (px, no unit) -->
<a href="https://example.com/map"
   data-wf-lightbox data-wf-type="iframe"
   data-wf-width="800" data-wf-height="500">
  View map
</a>

Play Button

Add the class wf-lightbox-play to a trigger wrapper to overlay a CSS-only play button on the thumbnail. Useful for video gallery cards where the thumbnail image should visually signal that clicking opens a video rather than a photo.

HTML
<a href="https://youtu.be/dQw4w9WgXcQ"
   data-wf-lightbox class="wf-lightbox-play">
  <img src="video-thumb.jpg" alt="Watch video">
</a>

Data Attributes

All attributes go on the trigger element ( <a> , <button> , or any other element).

Attribute Values Description
data-wf-lightbox Required. Marks the element as a lightbox trigger. Auto-inits on DOMContentLoaded.
data-wf-src URL Media URL to open. Falls back to the element’s href, then its src attribute.
data-wf-type auto · image · iframe · video · youtube · vimeo Force the media type. Default: auto (detected from URL).
data-wf-group string Gallery group name. All triggers sharing the same name form a navigable gallery with arrows, counter, and thumbnail strip.
data-wf-caption string Caption text shown below the media in the lightbox.
data-wf-thumb URL Thumbnail image for the gallery strip. Falls back to an <img> inside the trigger element.
data-wf-width integer (px) Override iframe or video width in pixels (no unit suffix). Has no effect on image or embed types.
data-wf-height integer (px) Override iframe or video height in pixels.

CSS Custom Properties

Declared on .wf-lightbox-overlay . Override on :root or any ancestor.

CSS
:root {
  --wf-lightbox-bg:         rgba(0, 0, 0, 0.92);
  --wf-lightbox-btn-size:   3rem;
  --wf-lightbox-radius:     0.75rem;
  --wf-lightbox-caption-bg: rgba(0, 0, 0, 0.65);
}
Property Default Description
--wf-lightbox-bg rgba(10,14,26,0.96) Overlay background color. Also receives a backdrop-filter: blur(6px) effect.
--wf-lightbox-btn-size 2.75rem Width and height of the close, previous, and next buttons.
--wf-lightbox-radius var(--wf-radius-5) Border radius of the media frame, images, videos, and iframes.
--wf-lightbox-caption-bg rgba(0,0,0,0.55) Background of the caption bar that appears beneath the media.

Programmatic API

The static WojoLightbox.open() and WojoLightbox.close() methods let you control the lightbox from JavaScript without any trigger element in the DOM.

JS
import { WojoLightbox } from './wf-lightbox.js'

// Open a single image
WojoLightbox.open({
  src:     'photo.jpg',
  type:    'image',
  caption: 'My caption',
})

// Open a YouTube video
WojoLightbox.open({
  src:  'https://youtu.be/dQw4w9WgXcQ',
  type: 'youtube',
})

// Close from outside
WojoLightbox.close()
Method Description
WojoLightbox.open(item) Open the lightbox with an arbitrary item object. Properties: src, type, caption, thumb, width, height. Closes any currently open lightbox first.
WojoLightbox.close() Close the currently open lightbox with the normal fade-out animation.

Events

Events are dispatched on the trigger element that opened the lightbox and bubble up the DOM. When opened via WojoLightbox.open() no trigger element is involved, so no events are fired.

JS
document.addEventListener('wf:lightbox-open', e => {
  console.log('Opened:', e.detail.src, e.detail.type)
  console.log('Trigger element:', e.detail.trigger)
})

document.addEventListener('wf:lightbox-close', () => {
  console.log('Lightbox closed')
})

document.addEventListener('wf:lightbox-change', e => {
  console.log(`Gallery: ${e.detail.index + 1} of ${e.detail.total}`)
})
Event detail Fired when
wf:lightbox-open { trigger, src, type } The lightbox opens. trigger is the clicked element; src and type are the resolved media values.
wf:lightbox-close The lightbox finishes its close animation and is removed from the DOM.
wf:lightbox-change { index, total } The gallery navigates to a different item. index is 0-based; total is the gallery size.

Class Reference

All overlay classes below are created and injected into <body> by the JS at open time and removed on close. The only class you add yourself is wf-lightbox-play on trigger wrappers.

Class Description
wf-lightbox-overlay Fixed the full-viewport overlay. Has role="dialog" and aria-modal="true". Receives wf-lb-closing during the close animation.
wf-lightbox-stage Content stage containing the frame, caption, and thumbnail strip. Receives wf-lb-slide-next or wf-lb-slide-prev during gallery navigation to trigger the slide animation.
wf-lightbox-frame Media frame. Contains the <img>, <video>, <iframe>, or video wrapper depending on media type.
wf-lightbox-video-wrap 16:9 responsive wrapper inserted around YouTube and Vimeo iframes.
wf-lightbox-spinner Spinning loader shown inside the frame while media is loading. Removed on load / canplay.
wf-lightbox-caption Caption bar rendered below the frame. Hidden when no caption is set.
wf-lightbox-counter Pill showing current position in a gallery (e.g. “2 / 5”). Hidden for single items.
wf-lightbox-close Close button, fixed top-right. Focuses automatically on open for keyboard accessibility.
wf-lightbox-prev Previous arrow button, fixed left. Hidden for single items.
wf-lightbox-next Next arrow button, fixed right. Hidden for single items.
wf-lightbox-thumbs Thumbnail strip container below the stage. Hidden when the gallery has fewer than two items or no items provide a thumb.
wf-lightbox-thumb Individual thumbnail in the strip. Receives wf-lb-thumb-active for the currently displayed item.
wf-lb-thumb-active State class on the active gallery thumbnail.
wf-lightbox-play Add to a trigger’s wrapper element to overlay a CSS-only circular play button on its thumbnail. No JS required.
wf-lb-closing State class is added to the overlay during the close animation. Removed when the overlay is destroyed.
wf-lb-slide-next / wf-lb-slide-prev Applied to .wf-lightbox-stage during gallery navigation to trigger the slide-in animation.
Show More