Gallery✨ Premium

Lightbox with Thumbnails

Large image with, right below it, a strip of every thumbnail: jump straight to the photo you want, or step through with ‹ ›, ← → and a finger.

JSThumbnailsStrip

Updated

This effect is part of Effect.Labs — 840 vanilla effects, some free, some premium. Gallery has 44 effects, including 6 free. Explore the category →

3 usage examples

Rooms of a mountain cottage, with the photo strip under the large view — Lightbox with Thumbnails example 1

① Rooms of a mountain cottage, with the photo strip under the large view

WhenOn the Talvèze cottage listing, the guest opens the living-room photo, then taps the bedroom miniature straight from the strip.
WhyFor a rental you want to go straight to the room that matters (bedroom, terrace) without scrolling through everything; the strip also shows how many photos are left.
SettingsMosaic gallery (one large view across two rows, two small ones), the fourth photo hidden in the mosaic but present in the strip. --tlb-backdrop: rgba(18, 26, 16, 0.94). Capture: opening, then a click on the strip's third miniature.
Choosing an announcement card design at step 2 of an order — Lightbox with Thumbnails example 2

② Choosing an announcement card design at step 2 of an order

WhenAt the Pomeranche paper shop, the customer opens “Starry night” and moves from one design to the next with › to compare, the strip showing where they are.
WhyComparing four printed designs means seeing them large, one after the other; the strip keeps all four choices in view meanwhile.
SettingsTwo-column grid in the order area, summary (format, quantity, price) alongside, pink --tlb-accent.
Versions V1 to V4 of a mockup sent to a studio's client — Lightbox with Thumbnails example 3

③ Versions V1 to V4 of a mockup sent to a studio's client

WhenIn Studio Cardolune's client area, the client opens V3, then compares it with V4 using the right arrow before leaving a comment.
WhyApproving a mockup means switching quickly between versions at the same spot on screen; keyboard and strip make the comparison instant.
SettingsFour-column grid with version number and name under each thumbnail; thumbnails outlined in grey (a box-shadow added by the scene). Capture: ArrowRight keydown sent to the dialog.

How it works

You only write the gallery once. On load, the script walks through the .tlb-thumb buttons and builds, inside .tlb-strip, a small button for each, with the same image and the same alt. The strip therefore always follows the gallery, however many photos it holds.

The miniature of the image on display is highlighted (full opacity, white border, 10 % larger) and carries aria-current="true"; the others stay half transparent. When the strip is wider than 80 % of the screen it scrolls horizontally and recentres the active miniature on every change.

The rest comes from the arrow viewer: looping ‹ ›, ← → keys, a horizontal drag of more than 50 px on the large image, Escape / ✕ / background click to close. The large image is limited to 80 % of the width and to the screen height minus 110 px, so the strip stays visible even on a phone held sideways.

Accessibility

  • Two ways to choose: strip miniatures are buttons named by their photo's alt, grouped in a role="group" called “Thumbnails”; the active one is flagged with aria-current.
  • Keyboard: Tab goes through ✕, ‹, ›, then each miniature; ← → change image from any button in the viewer; Escape closes.
  • Dialog: showModal(), named “Image viewer”, page behind inert, focus returned to the original thumbnail on closing.
  • Reduced motion: opening without fade or zoom, miniatures without transition; navigation and swiping remain available.

Browser compatibility

Base shared by the site's viewers (modal <dialog>: Firefox 98, Safari 15.4; aspect-ratio: Chrome 88). justify-content: safe center keeps an over-long strip from being cut off on the left; where safe is not understood, the preceding center declaration applies. Tried in Chromium 151, Firefox 153 and WebKit 26.5: strip built in each copy, click on the 4th miniature, touch at 390 px.

Chrome 88+✓ Full (measured)
Firefox 98+✓ Full (measured)
Safari 15.4+✓ Full (measured on WebKit)
Edge 88+✓ Full (Chromium engine)
Mobile iOS 15.4+✓ Full (not measured on a device)
Android Chrome 88+✓ Full (touch measured)

Without JavaScript the strip stays empty and nothing opens: only the gallery shows.

The code

HTML structure to paste into your page (the CSS + JS come with your purchase):

index.html — structure
<div class="fx-0175-root">
  <div class="tlb-grid">
    <button type="button" class="tlb-thumb" aria-haspopup="dialog"><img src="photo.jpg" alt="Violet to cyan gradient" width="600" height="400"></button>
    <button type="button" class="tlb-thumb" aria-haspopup="dialog"><img src="photo.jpg" alt="Cyan to emerald gradient" width="600" height="400"></button>
    <button type="button" class="tlb-thumb" aria-haspopup="dialog"><img src="photo.jpg" alt="Fuchsia to rose gradient" width="600" height="400"></button>
    <button type="button" class="tlb-thumb" aria-haspopup="dialog"><img src="photo.jpg" alt="Pink to violet gradient" width="600" height="400"></button>
  </div>
  <dialog class="tlb-viewer" aria-label="Image viewer">
    <div class="tlb-content">
      <button type="button" class="tlb-close" aria-label="Close"><svg>…</svg></button>
      <button type="button" class="tlb-nav tlb-prev" aria-label="Previous image"><svg>…</svg></button>
      <img class="tlb-image" alt="">
      <button type="button" class="tlb-nav tlb-next" aria-label="Next image"><svg>…</svg></button>
      <div class="tlb-strip" role="group" aria-label="Thumbnails"></div>
    </div>
  </dialog>
</div>

One-time payment, no subscription — the code is yours forever

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Gallery thumbnails (CSS — --tlb-thumb) 120px Width of the buttons on the page (3:2 format).
Strip miniatures (CSS — .tlb-strip-btn) 60 × 40 px Fixed size in the CSS; make them bigger and reduce the 110 px left under the large image by the same amount.
Large image height (CSS — max-height of .tlb-image) calc(80vh - 110px) The remaining space is the strip's; adjust it if you change the miniature size.
Overlay (CSS — --tlb-backdrop) rgba(0, 0, 0, 0.9) Viewer background.
Corners (CSS — --tlb-radius, --tlb-radius-lg) 0.5rem, 1rem Page thumbnails; large image and strip background.
Large version (HTML — data-full) absent The large view loads that URL; the strip keeps the light thumbnail.
Swipe threshold (JS — 50) 50 px Horizontal drag needed on the large image to change photo.

FAQ

No, leave <div class="tlb-strip"> empty: the script fills it from the gallery. It only sees the photos present when it runs: for a gallery built later, insert the whole root then run the script again (roots already wired are skipped).
The strip becomes scrollable (thin bar) and recentres on the active miniature at each change; the large image stays in place.
Yes, that is what the cottage scene does: hide the button in CSS (display: none); it is still counted, present in the strip and reachable with the arrows.