Now.js Framework Documentation
ImageGallery
ImageGallery
Overview
ImageGallery is an inline image gallery component for Now.js Framework. It renders a hero image with an optional thumbnail strip, and opens a fullscreen lightbox (via MediaViewer) when the image is tapped or clicked.
When to use:
- Displaying product or part images inside a card or modal
- Showing a photo set inside a form or a TemplateManager
data-forloop - Any place where images need to be browsable inline without navigating away
Why use it:
- ✅ Fully declarative — HTML only, zero custom JS required
- ✅ Auto-initialises via ComponentManager (works in templates, modals, API-loaded content)
- ✅ Multiple transition effects (fade, slide, none)
- ✅ Flexible thumbnail position (bottom, left, right, top)
- ✅ Fullscreen zoom via MediaViewer (swipe, pinch, keyboard)
- ✅ REST API support (
data-api) - ✅ Touch swipe navigation
- ✅ Keyboard navigation (← / →)
- ✅ Responsive with container queries
- ✅ Accessible (ARIA labels, focus management)
Basic Usage
Static HTML
<div data-component="image-gallery">
<img src="/images/photo1.jpg" alt="Front view" data-caption="Front view">
<img src="/images/photo2.jpg" alt="Side view" data-caption="Side view">
</div>Full-size vs thumbnail URLs
Use data-src for the full-size image. src is displayed as the thumbnail.
If only src is provided, the same URL is used for both.
<div data-component="image-gallery">
<img src="/thumbs/photo1_sm.jpg" data-src="/images/photo1.jpg" alt="Photo 1" data-caption="Photo 1">
<img src="/thumbs/photo2_sm.jpg" data-src="/images/photo2.jpg" alt="Photo 2">
</div>Transition effects
<!-- Fade (default) -->
<div data-component="image-gallery" data-effect="fade">...</div>
<!-- Slide -->
<div data-component="image-gallery" data-effect="slide">...</div>
<!-- No animation -->
<div data-component="image-gallery" data-effect="none">...</div>Aspect ratio
<!-- Square (1:1) -->
<div data-component="image-gallery" data-aspect="square">...</div>
<!-- Wide (16:9) -->
<div data-component="image-gallery" data-aspect="wide">...</div>
<!-- Tall (3:4) -->
<div data-component="image-gallery" data-aspect="tall">...</div>
<!-- Auto (natural image height) — default -->
<div data-component="image-gallery" data-aspect="auto">...</div>Thumbnail position
<!-- Bottom (default) -->
<div data-component="image-gallery" data-thumbnails-position="bottom">...</div>
<!-- Left side -->
<div data-component="image-gallery" data-thumbnails-position="left">...</div>
<!-- Right side -->
<div data-component="image-gallery" data-thumbnails-position="right">...</div>
<!-- Top -->
<div data-component="image-gallery" data-thumbnails-position="top">...</div>Hide thumbnails
Thumbnails are shown automatically when there are 2 or more images.
Set data-show-thumbnails="false" to always hide them.
<div data-component="image-gallery" data-show-thumbnails="false">
<img src="/images/hero.jpg" alt="Hero">
</div>Disable fullscreen zoom
<div data-component="image-gallery" data-enable-zoom="false">...</div>API-Driven Loading
Load images from a REST API endpoint. The component shows a loading indicator while fetching.
<div data-component="image-gallery" data-api="api/parts/images?id=5"></div><!-- POST endpoint -->
<div data-component="image-gallery"
data-api="api/products/gallery"
data-api-method="POST">
</div>Expected API response formats
The endpoint can return any of these formats:
["url1.jpg", "url2.jpg"][
{ "url": "photo1.jpg", "alt": "Front", "caption": "Front view" },
{ "url": "photo2.jpg", "thumb": "photo2_sm.jpg", "alt": "Side" }
]{ "data": [ ... ] }{ "items": [ ... ] }Item fields: url / src / path, thumb / thumbnail, alt, caption / title.
Usage with TemplateManager
Works inside data-for loops. ComponentManager auto-initialises each gallery after TemplateManager renders the loop.
Single image per card
<div data-for="item in results">
<div class="product-card">
<div data-component="image-gallery" data-aspect="square" data-show-thumbnails="false">
<img data-attr="src:item.image;alt:item.name" data-if="item.image" loading="lazy">
</div>
<div data-text="item.name"></div>
</div>
</div>Multiple images per item
When the API returns item.images[], use data-for on the <img> elements:
<div data-component="image-gallery" data-effect="fade">
<img data-for="img in item.images"
data-attr="src:img.url;alt:img.alt"
data-attr-extra="data-caption:img.caption"
loading="lazy">
</div>Usage inside Modal / ResponseHandler
When the server returns HTML containing data-component="image-gallery" via action.html,Modal.setContent() inserts the HTML into the DOM and CoreObserver fires ComponentManager
automatically — no extra JS needed.
PHP (Kotchasan controller)
// images array from model
$imgTags = '';
foreach ($part->images as $i => $img) {
$url = htmlspecialchars($img['url']);
$imgTags .= '<img src="'.$url.'" data-src="'.$url.'" alt="'.htmlspecialchars($part->name).'">';
}
$html = '<div data-component="image-gallery" data-effect="fade" '
. 'data-aspect="auto" data-thumbnails-position="bottom" '
. 'data-show-thumbnails="true" data-enable-zoom="true">'
. $imgTags
. '</div>';
// Return as modal action
$this->sendSuccess(['html' => $html, ...]);Programmatic API
Use ImageGallery.create() when you need to build a gallery entirely from JavaScript.
const gallery = ImageGallery.create(element, {
images: [
{ url: '/images/photo1.jpg', thumb: '/thumbs/photo1.jpg', alt: 'Photo 1', caption: 'Photo 1' },
{ url: '/images/photo2.jpg', alt: 'Photo 2' }
],
effect: 'slide',
aspect: 'wide',
thumbnailsPosition: 'bottom',
enableZoom: true
});
// Navigate to specific image
gallery.goTo(1);
// Replace all images at runtime
gallery.update(newImages);
// Remove gallery and clean up events
gallery.destroy();Data Attributes Reference
| Attribute | Values | Default | Description |
|---|---|---|---|
data-effect |
fade | slide | none |
fade |
Transition effect when switching images |
data-aspect |
square | wide | tall | auto |
auto |
Hero image aspect ratio |
data-show-thumbnails |
true | false |
true |
Show thumbnail strip (hidden when ≤ 1 image) |
data-thumbnails-position |
bottom | left | right | top |
bottom |
Position of thumbnail strip |
data-enable-zoom |
true | false |
true |
Enable fullscreen zoom via MediaViewer |
data-empty-icon |
CSS icon class | icon-picture |
Icon shown when no images |
data-api |
URL string | — | REST API endpoint to load images from |
data-api-method |
GET | POST |
GET |
HTTP method for API request |
Image <img> Attributes
| Attribute | Description |
|---|---|
src |
Thumbnail URL (displayed in the thumbnail strip) |
data-src |
Full-size URL (used in fullscreen viewer). Falls back to src if not set |
alt |
Alt text for accessibility |
data-caption |
Caption shown below hero image. Falls back to alt |
Programmatic API Reference
ImageGallery.create(element, options)
Create a gallery programmatically on an existing element.
| Parameter | Type | Description |
|---|---|---|
element |
HTMLElement |
Container element |
options.images |
Array |
Array of image objects |
options.effect |
string |
fade | slide | none |
options.aspect |
string |
square | wide | tall | auto |
options.showThumbnails |
boolean |
Show thumbnail strip |
options.thumbnailsPosition |
string |
bottom | left | right | top |
options.enableZoom |
boolean |
Enable fullscreen viewer |
options.emptyIcon |
string |
CSS class for empty state icon |
Returns an instance object with:
| Method | Description |
|---|---|
goTo(index) |
Navigate to image at index |
update(newItems) |
Replace all images and rebuild |
destroy() |
Remove events and clean up |
Keyboard & Touch Controls
| Control | Action |
|---|---|
← / → |
Previous / Next image (when gallery or a child has focus) |
| Click / Tap hero | Open fullscreen MediaViewer |
| Zoom button (hover) | Open fullscreen MediaViewer |
| Swipe left / right | Next / Previous image |
CSS Classes Reference
| Class | Description |
|---|---|
.ig |
Root element |
.ig--fade / .ig--slide / .ig--none |
Active effect modifier |
.ig--square / .ig--wide / .ig--tall / .ig--auto |
Active aspect modifier |
.ig--bottom / .ig--left / .ig--right / .ig--top |
Active thumbnail position |
.ig-hero |
Hero image container |
.ig-main-img |
The displayed <img> |
.ig-zoom-btn |
Fullscreen zoom button (visible on hover) |
.ig-caption |
Caption text below hero |
.ig-thumbs |
Thumbnail strip container |
.ig-thumb |
Individual thumbnail button |
.ig-thumb.is-active |
Currently viewed thumbnail |
.ig-empty |
Modifier when no images |
.ig-loading |
Modifier while loading from API |
Integration with MediaViewer
When data-enable-zoom="true" (default), clicking the hero or the zoom button callsMediaViewer.show() with all images starting at the current index.MediaViewer provides zoom, pan, keyboard, touch, and autoplay for the fullscreen view.
MediaViewer is loaded automatically as part of the core bundle.
Related
- MediaViewer — Fullscreen lightbox used by ImageGallery for zoom
- ComponentManager — Handles auto-init lifecycle
- TemplateManager —
data-for,data-if,data-attrdirectives