Gallery✨ Premium

Lightbox with Caption

Arrow viewer with a caption under the photo — title and detail read from your HTML — that rises and fades in on opening.

JSCaptionAnimated

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

Fossils in a museum's online collection, with species and age — Lightbox with Caption example 1

① Fossils in a museum's online collection, with species and age

WhenOn the Sornevil Natural History Museum site, the visitor filters fossils and opens the Otodus tooth; the caption gives genus, period and age, then › loops back to the start of the series, the ammonite.
WhyA fossil photo says nothing without its name and date; the caption under the image adds that information without hiding it under overlaid text.
SettingsGrid of four square thumbnails, --clb-backdrop: rgba(20, 18, 15, 0.95). Captions are written as data-title / data-desc on each button.
Shared travel log: stop and date under each landscape — Lightbox with Caption example 2

② Shared travel log: stop and date under each landscape

WhenLéa's family opens the first photo of the trip and follows the route with the right arrow, from the lake to the mountain hut, reading the day under each image.
WhyIn a travel story order matters: the “Day 4 · 15 July” caption gives the thread, and the keyboard lets you unroll the trip without aiming.
Settings2 × 2 grid in a white card, a “← →” note under the grid. Capture: ArrowRight keydown sent to the dialog.
Before / after photos in a plumber's job report — Lightbox with Caption example 3

③ Before / after photos in a plumber's job report

WhenIn Corvisane Plumbing's report no. 2481, the customer clicks the photo of the leak, then › to see the new joint and the checked water heater.
WhyThese photos are evidence: the “Before / After” caption, date and room under each image settle any question about what was done.
SettingsThree 84 px thumbnails in the body of the report, under the “Photos” heading. Report-blue --clb-accent.

How it works

The caption comes from two attributes on each .clb-thumb button: data-title (the bold title) and data-desc (the grey line: place, date or detail). Without data-title, the photo's alt becomes the title; without data-desc, the second line is hidden. Changing a text in the HTML is enough; the script holds no captions.

The viewer is a <figure> inside a modal <dialog>: the photo, then a <figcaption>. On opening, the caption starts 20 px lower and transparent, then rises over 0.4 s after a 0.2 s delay, just after the image arrives. From then on, ‹ › (looping), ← → and a horizontal drag of more than 50 px on the photo change the image and its caption together.

To keep the caption visible, the photo is limited to the screen height minus 130 px (and to 80 % of its width). Close with ✕, Escape or a click on the background.

Accessibility

  • Caption tied to the image: <figure> + <figcaption>, and the caption is an aria-live="polite" region: each new caption is read when moving to the next photo.
  • Named buttons: thumbnails, ‹ “Previous image”, › “Next image”, ✕ “Close”.
  • Modal dialog: named “Image viewer”, focus on ✕ on opening, page behind inert, focus returned to the thumbnail.
  • Reduced motion: the caption appears directly, with no rise or fade, like the image.

Browser compatibility

Same base as the other viewers: modal <dialog> (Chrome 37, Firefox 98, Safari 15.4) and aspect-ratio (Chrome 88). Checked in Chromium 151, Firefox 153 and WebKit 26.5: caption changed in the HTML then read on opening, only one copy opened when two galleries share the page, script pasted twice with no skipped caption.

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 showModal(), nothing opens; your texts stay in the attributes, unseen. To have them read even without the script, repeat them in the alt.

The code

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

index.html — structure
<div class="fx-0177-root">
  <div class="clb-grid">
    <button type="button" class="clb-thumb" aria-haspopup="dialog" data-title="Northern lights" data-desc="Norway, 2024"><img src="photo.jpg" alt="Indigo to violet gradient" width="600" height="400"></button>
    <button type="button" class="clb-thumb" aria-haspopup="dialog" data-title="Sunset" data-desc="Cyclades, Greece"><img src="photo.jpg" alt="Fuchsia to rose gradient" width="600" height="400"></button>
    <button type="button" class="clb-thumb" aria-haspopup="dialog" data-title="Mystic forest" data-desc="Amazon, Brazil"><img src="photo.jpg" alt="Violet to cyan gradient" width="600" height="400"></button>
    <button type="button" class="clb-thumb" aria-haspopup="dialog" data-title="Pacific Ocean" data-desc="Hawaii, USA"><img src="photo.jpg" alt="Cyan to emerald gradient" width="600" height="400"></button>
  </div>
  <dialog class="clb-viewer" aria-label="Image viewer">
    <figure class="clb-content">
      <button type="button" class="clb-close" aria-label="Close"><svg>…</svg></button>
      <button type="button" class="clb-nav clb-prev" aria-label="Previous image"><svg>…</svg></button>
      <img class="clb-image" alt="">
      <button type="button" class="clb-nav clb-next" aria-label="Next image"><svg>…</svg></button>
      <figcaption class="clb-caption" aria-live="polite">
        <strong class="clb-title"></strong>
        <span class="clb-desc"></span>
      </figcaption>
    </figure>
  </dialog>
</div>

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

Customize

Options passed to the API or data-* attributes:

Option / propertyDefaultEffect
Caption title (HTML — data-title) the image alt Bold text under the photo.
Second line (HTML — data-desc) empty (line hidden) Place, date, author… in grey under the title.
Height left for the caption (CSS — max-height of .clb-image) calc(80vh - 130px) Increase the 130 px for captions on several lines.
Caption rise (CSS — .clb-caption) 20 px, 0.4 s after 0.2 s Starting transform and transition; set them to zero for a static caption.
Second line colour (CSS — .clb-desc) #8b8b93 A grey that stays readable on the black background.
Thumbnails and overlay (CSS — --clb-thumb, --clb-backdrop) 120px, rgba(0, 0, 0, 0.9) Width of the page buttons and viewer background.
Large photo (HTML — data-full) absent URL loaded into the viewer instead of the thumbnail.

FAQ

On each button: <button class="clb-thumb" data-title="Corlanne viaduct" data-desc="May 2024">. The script reads them when the photo is shown; there is nothing to change in the JavaScript.
No: the attributes are copied as plain text (textContent), which also stops code from slipping in by mistake. For a rich caption you would replace textContent with your own template.
No, only on opening. After that the text changes together with the photo, without animation, so reading a series is not slowed down.