NitroLitebox
Install NitroLiteBox, activate it, and your existing WordPress galleries and linked images gain a full-screen lightbox with pan & zoom, gallery grouping, and keyboard/touch navigation - no configuration required.
Overview
NitroLiteBox adds a full-screen lightbox to every linked image on your site. It loads just two files - a CSS file and a JS file - both deferred so they never block page rendering.
The plugin is designed to be set-and-forget: activate it and your existing WordPress gallery blocks, media links, and Oxygen Builder galleries immediately gain lightbox behaviour, with no classes or attributes to add.
Key design decisions
- Zero dependencies - pure vanilla JavaScript. No jQuery, no Lodash, no icon fonts.
- GPU-only animations - all transitions use
transformandopacity. No layout thrashing. - Deferred loading - the
strategy: deferflag means the JS never blocksDOMContentLoaded. - Adjacent preloading - the next and previous images in a gallery are preloaded silently as soon as the lightbox opens.
- Accessible by default -
role="dialog",aria-modal, focus trap, focus-visible ring, andprefers-reduced-motionsupport.
Installation
Method A - WordPress Admin (recommended)
- Go to Plugins → Add New Plugin → Upload Plugin.
- Choose
nitrolitebox.zipand click Install Now. - Click Activate Plugin.
Method B - FTP / SFTP
- Unzip
nitrolitebox.zip. - Upload the
nitrolitebox/folder to/wp-content/plugins/. - Activate via Plugins → Installed Plugins.
Requirements
| Requirement | Minimum | Notes |
|---|---|---|
| WordPress | 5.5 | Tested up to 6.7 |
| PHP | 7.4 | No PHP extensions required |
| Browser | ES6+ | All evergreen browsers; IE not supported |
| jQuery | Not required | |
Settings Page
Access all settings at Settings → NitroLiteBox in your WordPress admin. Changes are saved immediately and passed to the frontend via wp_localize_script.
- Auto-detect images - toggle automatic lightbox on all linked images in content
- Extra selectors - comma-separated CSS selectors for additional elements to lightbox
- Caption source - how NitroLiteBox finds caption text (auto, title, alt, or none)
- Counter position - where the "1 / 4" counter appears (top, bottom, or hidden)
- Enable pan & zoom - toggle the entire zoom feature
- Max zoom level - maximum multiplier (2-10, default 4×)
- Group class prefix - the CSS class prefix used for auto-grouping (default
nlb-group-)
All Options
These are all available configuration keys. They can be set via the Settings page or the nitrolitebox_options filter.
| Key | Type | Default | Description |
|---|---|---|---|
autoInit |
bool | true | Auto-detect <a><img> pairs in content |
selector |
string | "" | Extra CSS selectors (comma-separated) to lightbox |
captionSource |
string | "auto" | Where to read caption from: auto, title, alt, none |
loop |
bool | true | Loop from last image back to first (and vice versa) |
keyboard |
bool | true | Enable arrow key and Escape keyboard navigation |
swipe |
bool | true | Enable left/right swipe navigation on touch devices |
zoomIn |
bool | true | Scale-up entrance animation when image opens |
zoom |
bool | true | Enable full pan & zoom feature |
zoomMax |
number | 4 | Maximum zoom multiplier |
zoomStep |
number | 0.4 | Scroll-wheel zoom step size per tick |
groupClassPrefix |
string | "nlb-group-" | CSS class prefix for automatic gallery grouping |
counterPos |
string | "top" | Position of "1 / 4" counter: top, bottom, none |
PHP Filter
Override any option programmatically using the nitrolitebox_options filter in your theme's functions.php. This takes priority over the Settings page.
add_filter( 'nitrolitebox_options', function( $options ) {
// Disable zoom on this site
$options['zoom'] = false;
// Increase max zoom
$options['zoomMax'] = 6;
// Use a custom class prefix for grouping
$options['groupClassPrefix'] = 'gallery-set-';
// Always use alt text for captions
$options['captionSource'] = 'alt';
return $options;
} );
Auto-Detection
When autoInit is true (the default), NitroLiteBox scans the page for any <a> element that:
- Has an
hrefpointing to an image file (jpg, png, gif, webp, avif, svg, bmp, tiff) - Contains an
<img>element
This matches the exact HTML output of WordPress core gallery blocks, the Classic Editor's "Link to media file" option, and Oxygen Builder's gallery widget.
<!-- This is detected and lightboxed automatically -->
<a href="image-full.jpg">
<img src="image-thumb.jpg" alt="A description">
</a>
Extra selectors
To lightbox links that don't wrap an <img> (e.g. text links to images), add their CSS selector in Settings → Extra selectors or via the filter:
$options['selector'] = '.hero-section a, .portfolio-item > a';
Shortcode
Use the shortcode when you need precise control over the thumbnail, caption, or group assignment - especially useful in the Block Editor or Classic Editor.
[nitrolitebox
src="https://picsum.photos/1200/800"
thumb="https://picsum.photos/400/300"
caption="Sunset over the bay"
group="gallery-landscapes"
class="my-extra-class"
width="400"
height="300"
]
Shortcode parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
src |
Yes | - | URL of the full-size image to display in the lightbox |
thumb |
No | Same as src | URL of the thumbnail to show on the page |
caption |
No | "" | Caption text shown in the lightbox overlay |
group |
No | Auto per-post ID | Group name for gallery navigation |
class |
No | "" | Extra CSS classes on the generated <a> tag |
width |
No | "" | Width attribute for the thumbnail <img> |
height |
No | "" | Height attribute for the thumbnail <img> |
Gallery Grouping New in v1.1
When multiple images share a group identifier, clicking any one of them opens the full set as a browsable gallery with prev/next navigation and a "1 / 4" counter.
Method 1 - CSS class (new in v1.1)
Add the same class starting with nlb-group- to any number of <a> tags. NitroLiteBox promotes the class to a group automatically.
<a href="photo1.jpg" class="nlb-group-portfolio"><img src="thumb1.jpg"></a>
<a href="photo2.jpg" class="nlb-group-portfolio"><img src="thumb2.jpg"></a>
<a href="photo3.jpg" class="nlb-group-portfolio"><img src="thumb3.jpg"></a>
<!-- All three are grouped - clicking any opens the full set -->
nlb-group- to any string in Settings or via $options['groupClassPrefix'].Method 2 - rel attribute
WordPress core gallery blocks already output rel="..." on all images in a gallery. NitroLiteBox reads this automatically - no changes needed.
<a href="photo1.jpg" rel="gallery-landscapes"><img src="thumb1.jpg"></a>
<a href="photo2.jpg" rel="gallery-landscapes"><img src="thumb2.jpg"></a>
Method 3 - data-nlb-group attribute
For full manual control. Takes priority over class and rel if all three are present on the same element.
<a href="photo1.jpg" data-nlb-group="my-set">...</a>
<a href="photo2.jpg" data-nlb-group="my-set">...</a>
Priority order
When an element has multiple group identifiers, NitroLiteBox uses this priority:
data-nlb-groupattribute (highest priority)- CSS class matching the
groupClassPrefix relattribute- Standalone (no grouping)
Data Attributes
| Attribute | Element | Description |
|---|---|---|
data-nitrolitebox |
<a> | Explicitly mark any link as a lightbox trigger, even without an inner <img> |
data-nlb-group |
<a> | Assign to a named gallery group. All links sharing the same value form a gallery. |
data-nlb-caption |
<a> | Override caption text. Takes priority over title, alt, and figcaption. |
<a
href="https://example.com/image.jpg"
data-nitrolitebox
data-nlb-group="hero-set"
data-nlb-caption="The main event"
>
View full image
</a>
Pan & Zoom New in v1.1
The zoom feature is enabled by default. All zoom operations use GPU-composited transform: scale() - no repaints, smooth even on low-end mobile.
Zoom interactions
| Input | Action |
|---|---|
| Scroll wheel | Zoom in/out toward cursor position (pointer-anchored) |
| Double-click | Zoom to 2.5× at click point; double-click again to reset |
| Pinch gesture | Two-finger pinch-to-zoom on mobile, anchored at pinch midpoint |
| Click & drag | Pan image while zoomed in (edge-clamped) |
| One-finger swipe (zoomed) | Pan image (swipe navigation disabled while zoomed) |
| Zoom button | Toggle 1× ↔ 2× via the magnifier button (top-right of lightbox) |
| + / = | Zoom in one step |
| - | Zoom out one step |
| 0 | Reset zoom to 1× |
| Esc | If zoomed: reset zoom. If not zoomed: close lightbox. |
Behaviour while zoomed
- The prev/next navigation arrows dim to 25% opacity and become non-interactive.
- Swipe navigation is disabled (single-finger drag pans instead).
- Caption fades to 30% opacity to reduce distraction.
- A subtle hint text appears top-left: "ESC or 0 to reset zoom".
- The backdrop click does not close the lightbox while zoomed (prevents accidental closes mid-pan).
Disable zoom entirely
add_filter( 'nitrolitebox_options', function( $opts ) {
$opts['zoom'] = false;
return $opts;
} );
Keyboard & Touch
| Input | Action |
|---|---|
| → Arrow Right | Next image |
| ← Arrow Left | Previous image |
| Esc | Reset zoom (if zoomed) or close lightbox |
| + / = | Zoom in one step |
| - | Zoom out one step |
| 0 | Reset zoom |
| Swipe left | Next image (when not zoomed) |
| Swipe right | Previous image (when not zoomed) |
| Swipe (when zoomed) | Pan the image |
| Pinch | Zoom in/out |
Captions
NitroLiteBox resolves caption text in this order when captionSource is set to auto:
data-nlb-captionattribute on the<a>(highest priority)titleattribute on the<a>titleattribute on the inner<img>altattribute on the inner<img><figcaption>text inside an ancestor<figure>
You can lock the source to a single attribute using the captionSource option: title, alt, or none.
Preloading
As soon as a gallery image is shown, NitroLiteBox silently preloads the next and previous images using new Image() objects. Cached URLs are skipped. This means navigating to an adjacent image in the gallery is almost always instant.
JavaScript API
NitroLiteBox exposes a global window.NitroLiteBox object with the following methods.
NitroLiteBox.open(src, startIdx?)
Programmatically open the lightbox with one or more images.
// Single image
NitroLiteBox.open('https://example.com/photo.jpg');
// Gallery of images - second argument is the starting index
NitroLiteBox.open([
{ src: 'https://example.com/a.jpg', caption: 'First photo' },
{ src: 'https://example.com/b.jpg', caption: 'Second photo' },
{ src: 'https://example.com/c.jpg' },
], 1); // opens at index 1 (second image)
NitroLiteBox.refresh()
Re-scans the DOM for newly added images. Call this after dynamically inserting content (AJAX, infinite scroll, Oxygen dynamic render, etc.).
// Call after inserting new content
fetch('/api/more-images').then(res => {
container.innerHTML = res.html;
NitroLiteBox.refresh(); // scan for new links
});
// Or dispatch the custom event
document.dispatchEvent(new CustomEvent('nlb:refresh'));
NitroLiteBox.close()
Close the lightbox programmatically.
NitroLiteBox.next() / .prev()
Navigate to the next or previous image in the current gallery.
NitroLiteBox.setZoom(scale)
Set zoom to a specific multiplier (1 = normal, 2 = 2×, etc.). Animates to the new scale.
NitroLiteBox.setZoom(3); // zoom to 3×
NitroLiteBox.resetZoom(); // reset to 1×
Events
| Event | Target | Description |
|---|---|---|
nlb:ready |
document | Fired once after the first DOM scan completes on DOMContentLoaded |
nlb:refresh |
document | Listen or dispatch to trigger a DOM re-scan |
// Know when NitroLiteBox has initialised
document.addEventListener('nlb:ready', () => {
console.log('NitroLiteBox ready');
});
// Trigger a re-scan from anywhere
document.dispatchEvent(new CustomEvent('nlb:refresh'));
Builder Compatibility
Oxygen Builder
NitroLiteBox detects whether Oxygen is active (via the CT_VERSION constant) and injects an extra re-init block in wp_footer. This calls NitroLiteBox.refresh() on both DOMContentLoaded and a custom oxygen-done event. Oxygen's gallery widgets output standard <a href="full.jpg"><img> markup, so auto-detection works without any extra configuration.
Elementor
Elementor's gallery widget also outputs standard linked image markup. NitroLiteBox works out of the box. For AJAX-loaded Elementor sections, call NitroLiteBox.refresh() or dispatch nlb:refresh after the section loads.
Beaver Builder / Bricks
Both output standard HTML. Auto-detection covers them automatically.
Custom builders or AJAX content
// After your builder/AJAX inserts new HTML:
NitroLiteBox.refresh();
// Or, if you prefer events:
document.dispatchEvent(new CustomEvent('nlb:refresh'));
Changelog
v1.1.0
- Added full pan & zoom - scroll-wheel, double-click, pinch-to-zoom, drag-to-pan
- Added class-based gallery grouping - any shared
nlb-group-*class auto-groups images - Added zoom toggle button (magnifier icon, top-right of lightbox)
- Added keyboard shortcuts: +/- zoom, 0 reset zoom
- Esc now resets zoom first before closing, preventing accidental dismissal
- Navigation arrows dim and disable while zoomed
- Added
NitroLiteBox.setZoom()andNitroLiteBox.resetZoom()to the JS API - Settings: added Zoom enable/disable, Max zoom level, Group class prefix fields
- PHP: added
zoom,zoomMax,zoomStep,groupClassPrefixto options
v1.0.0
- Initial release
- Zero-dependency lightbox with auto-detection
- Gallery grouping via
relanddata-nlb-group - Swipe navigation, keyboard navigation
- Entrance zoom animation
- Frosted-glass button UI
- Caption with gradient overlay
- Adjacent image preloading
- Oxygen Builder re-init hook
- REST endpoint for attachment metadata
- Settings page, shortcode, PHP filter
FAQ
Will it conflict with my theme's existing lightbox?
Only if both plugins bind click handlers to the same links. Disable autoInit in Settings and use data-nitrolitebox attributes or the shortcode on specific elements to avoid conflicts.
Does it work with lazy-loaded images?
Yes. NitroLiteBox reads the href of the wrapping <a> tag to get the full-size URL, not the src of the thumbnail. Lazy-loading the thumbnail has no effect.
Can I use it without WordPress?
Yes - include nitrolitebox.css and nitrolitebox.js on any HTML page and call NitroLiteBox.refresh() after the DOM is ready. The PHP plugin wrapper is only needed for WordPress integration.
My images are loaded via AJAX. How do I re-init?
Call NitroLiteBox.refresh() after inserting the new HTML, or dispatch document.dispatchEvent(new CustomEvent('nlb:refresh')).
How do I change the background colour?
$opts['bgColor'] = 'rgba(20, 10, 30, 0.97)';
The zoom button tooltip is covering my image
The tooltip is CSS-only and only appears on button hover. To hide it entirely, add to your theme CSS: #nlb-zoom-btn::after { display: none !important; }
Does it support SVG images?
Yes - SVG is in the image extension regex. Full-size SVG files open in the lightbox like any other image.
Is it GDPR-friendly?
Yes. NitroLiteBox makes zero external requests. All assets load from your own server.