Build a custom lightbox gallery for your VTU script screenshots
Screenshots do the heavy lifting when you promote a VTU platform online. They let a visitor see the dashboard, the reseller page and the airtime-to-cash tool before committing to a demo. A well-arranged gallery turns a static product page into a guided tour, and a custom lightbox lets viewers zoom into the detail that matters, from transaction histories to admin settings.
Building a gallery from scratch gives you control over branding, file size and behaviour in a way that off-the-shelf plugins rarely allow. You decide the breakpoints, the animation curve and the way captions appear, so the result matches the rest of your site instead of fighting against it. For Nigerian operators serving customers in Lagos, Abuja and Port Harcourt, and for resellers in regional hubs, a tailored gallery also keeps the codebase small.
Australian small business owners and side hustlers who resell airtime and data form a sizeable slice of the international VTU market. Many run their operations from home offices in Sydney, Melbourne, Brisbane or Perth, often juggling the platform alongside a day job. They favour lean, fast-loading pages because NBN upload speeds vary widely between suburbs and every extra kilobyte costs them a click.
This walkthrough focuses on a lightweight, dependency-free approach that works on any modern browser. You will write semantic HTML, style the components with plain CSS, and add a small JavaScript file to handle clicks, swipes and keyboard input. By the end you will have a reusable module you can drop into any page of your VTU site.
Planning the gallery layout and user flow
Before you touch a code editor, sketch the gallery on paper. Decide how many thumbnails fit in a row on a phone, a tablet and a laptop, and think about the order a visitor should see your screenshots. Most VTU product tours work best when they start with the public reseller page, move to the customer wallet, then finish with the admin panel.
Think about the actions a user will take. They tap a thumbnail, the lightbox opens over a dimmed background, and the full-size screenshot appears with a caption. They swipe or use arrow keys to move through the set, close the modal with a tap on the dark area or the Escape key, and return to the page without losing scroll position.
Consider file naming and alt text early. Australian privacy guidance, including the Australian Privacy Principles set out by the Office of the Australian Information Commissioner, applies if your screenshots show real customer names, phone numbers or wallet balances. Blur or crop those details before you upload, and write alt text that describes the feature rather than personal data visible in the frame.
Writing semantic HTML for the thumbnail and modal
The HTML behind a lightbox gallery is shorter than most people assume. A container holds a row of anchor tags, each linking to a full-size image and carrying a data attribute that holds the caption text. A separate modal element sits at the end of the body and stays hidden until JavaScript populates it.
<section class="screenshot-gallery" aria-label="VTU script screenshots">
<a href="images/dashboard-full.jpg" data-caption="Reseller dashboard">
<img src="images/dashboard-thumb.jpg" alt="Reseller dashboard preview" loading="lazy" width="320" height="200">
</a>
</section>
<div id="lightbox" class="lightbox" hidden role="dialog" aria-modal="true" aria-labelledby="lightbox-caption">
<button class="lightbox-close" aria-label="Close gallery">×</button>
<button class="lightbox-prev" aria-label="Previous image">‹</button>
<img class="lightbox-image" src="" alt="">
<button class="lightbox-next" aria-label="Next image">›</button>
<p id="lightbox-caption" class="lightbox-caption"></p>
</div>
The role="dialog" and aria-modal="true" attributes tell assistive technology that the lightbox behaves like a modal window. The hidden attribute keeps the element out of the tab order until JavaScript removes it. Using real <button> elements for close, previous and next ensures keyboard users can reach those controls, which matters for visitors who navigate by keyboard because of motor impairment or temporary injury.
Keep the thumbnail markup consistent. Every anchor should carry the same data attributes so the JavaScript file can read them in a predictable order. If you maintain multiple galleries on the site, use a small naming pattern, such as gallery-v1-dashboard-thumb.jpg, so the asset library stays tidy when the marketing team uploads new shots each quarter.
Styling the gallery with modern CSS
A small CSS file is enough to make the gallery responsive and visually pleasant. Use CSS Grid for the thumbnail row so the columns reflow without media queries, and apply object-fit: cover to thumbnails so screenshots of slightly different aspect ratios still align.
.screenshot-gallery {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
gap: 12px;
}
.screenshot-gallery img {
width: 100%;
height: 160px;
object-fit: cover;
border-radius: 8px;
cursor: zoom-in;
}
.lightbox {
position: fixed;
inset: 0;
background: rgba(15, 23, 42, 0.85);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
}
The auto-fill keyword with a minmax value lets the grid squeeze as many columns as possible into the available width. On phones you see two columns, on tablets three or four, and on desktop monitors a sensible row that respects the container.
For Australian users on slower NBN connections or on mobile data in regional areas, lean CSS pays off. There is no external library to download, no font to fetch, and the entire stylesheet is usually under two kilobytes. If you host the file on a local server rather than a global CDN, visitors in Adelaide, Hobart or Darwin still receive the styles instantly without crossing international links.
Adding interactive JavaScript behaviour
The JavaScript layer is where the gallery comes alive. Attach a click listener to each thumbnail, prevent the default link behaviour, and populate the modal with the matching image and caption. A small state object tracks the current index so the previous and next buttons know which image to load.
const triggers = document.querySelectorAll('.screenshot-gallery a');
const lightbox = document.getElementById('lightbox');
const lbImage = lightbox.querySelector('.lightbox-image');
const lbCaption = document.getElementById('lightbox-caption');
let index = 0;
function show(i) {
index = (i + triggers.length) % triggers.length;
const link = triggers[index];
lbImage.src = link.href;
lbImage.alt = link.querySelector('img').alt;
lbCaption.textContent = link.dataset.caption;
lightbox.hidden = false;
document.body.style.overflow = 'hidden';
}
triggers.forEach((link, i) => {
link.addEventListener('click', e => {
e.preventDefault();
show(i);
});
});
document.addEventListener('keydown', e => {
if (lightbox.hidden) return;
if (e.key === 'Escape') lightbox.hidden = true;
if (e.key === 'ArrowRight') show(index + 1);
if (e.key === 'ArrowLeft') show(index - 1);
});
The modulo operator on the index keeps the navigation circular, so pressing next on the last screenshot returns to the first. Trapping the keyboard handler inside the lightbox.hidden check means arrow keys only act on the gallery when it is open, and Escape only closes it once triggered. This avoids the bug where arrow keys scroll the page behind the modal.
If you want a swipe gesture for touch devices, add a pair of touchstart and touchend listeners that compare horizontal movement. A swipe distance of more than fifty pixels in either direction is a reliable threshold for mobile users in Australian capital cities and regional centres alike.
Accessibility, performance and local testing
A gallery that looks good but breaks for some users is a missed opportunity. Run through the page with the keyboard only and confirm that Tab moves focus through the thumbnails in order, that Enter opens the lightbox, and that focus shifts into the modal so the close button receives the first stop. When the modal closes, return focus to the original thumbnail so a screen reader user knows where they are on the page.
Compress every screenshot before uploading. Tools such as Squoosh, ImageOptim or a build step with Sharp can shrink PNGs and JPEGs by sixty to eighty percent without visible quality loss. Serve images in WebP where the target audience uses modern browsers, and provide a JPEG fallback through the <picture> element if you want to support older machines. These small wins matter in a country where the Australian Bureau of Statistics reports that a meaningful share of households still rely on mobile-only internet access during parts of the day.
Test on a real phone over a real mobile network, not just on the office Wi-Fi. A gallery that loads in under a second on a Telstra or Optus 5G connection in the Sydney CBD may take three or four seconds on a 4G signal in a regional town, and the perceived experience changes accordingly.
Drop the finished gallery into your VTU site today and watch how visitors interact with the screenshots. The result turns a static product page into a portfolio piece that sells the script while the visitor is still browsing. Wire it into your homepage, sales page and feature tour, and the same component will carry the brand across every touchpoint without adding a single dependency to your stack.