liftbox

Deep linking

Keep the open slide in the URL hash with useLightboxHash.

useLightboxHash keeps the open slide in the URL, as #prefix-3. People can share a link to a photo, and the browser's back button closes the viewer.

It returns the same [index, setIndex] pair as useState(-1), so it drops into the quick start code:

import { Lightbox, useLightboxHash } from "liftbox";

const [index, setIndex] = useLightboxHash("photo", { count: slides.length });

<Lightbox
  slides={slides}
  open={index >= 0}
  index={Math.max(index, 0)}
  onIndexChange={setIndex}
  onClose={() => setIndex(-1)}
/>;

Open a photo below and watch the address bar. Then press the back button.

Live demo. Click a thumbnail to open it.

URLs

URLState
/photos#photo-3Open on the third slide. 1-based.
/photos#photo-harbour, with namesOpen on the slide named harbour
/photos, /photos#contact, /photos#photo-99Closed

History

  • Opening adds one history entry. Changing slide replaces it, so history does not fill up.
  • Closing goes back to the entry that was there before, which restores the previous URL, hash and scroll position. Back closes the viewer and forward opens it again.
  • When the page was loaded with the hash, because someone followed a shared link, closing removes the hash in place instead of leaving the page.
  • The state is read from the URL, so the URL and the lightbox cannot drift apart or loop.
  • Hashes that do not match the prefix, query strings and paths are never touched.

Options

OptionDescription
countNumber of slides. Hashes past it read as closed instead of an empty slide.
namesOne unique name per slide, in order. The URL shows the name instead of the number. Sets count for you.

Use a different prefix for each gallery on a page.

Named slides

A number changes when you reorder or filter the photos, so a link shared last month can open the wrong one. Pass names to put a stable name in the URL instead:

const [index, setIndex] = useLightboxHash("photo", {
  names: photos.map((photo) => photo.slug),
});

The third slide then lives at #photo-harbour rather than #photo-3. Names are encoded with encodeURIComponent, so spaces and accents are fine, but short slugs make nicer links. Numbered links still open, which keeps links shared before you added names working.

A shared link previews with your page's Open Graph image, not the photo, because sites that build link previews ignore everything after #. To preview the photo itself, give each one a real URL with its own og:image, such as /photos/harbour, and return it from share.url.

Server rendering

On the server and during hydration the hook reads -1. A gallery opened from a shared link opens right after hydration.

Edit this page on GitHub

On this page