@zachtrice/react-lightbox
v0.1.1
Published
Tiny, accessible, dependency-free React lightbox for click-to-enlarge images: ESC + backdrop close, scroll lock, focus handling, and a portal.
Maintainers
Readme
@zachtrice/react-lightbox
A tiny, accessible, dependency-free React lightbox for click-to-enlarge
images. No CSS import, no config: pass an image src and an onClose.
- Full-screen overlay rendered in a portal (never clipped by parent overflow / stacking context).
- Close on Escape, backdrop click, or the close button.
- Scroll lock while open and basic focus handling.
- Inline styles, so there is nothing to import or configure.
- Ships types. ~1 KB, only
react+react-domas peers.
Install
npm install @zachtrice/react-lightboxUsage
With the useLightbox hook (recommended):
import { Lightbox, useLightbox } from '@zachtrice/react-lightbox'
function Gallery({ photos }: { photos: { thumb: string; full: string; caption: string }[] }) {
const { open, close, src, alt } = useLightbox()
return (
<>
{photos.map((p) => (
<img key={p.full} src={p.thumb} alt={p.caption}
style={{ cursor: 'zoom-in' }} onClick={() => open(p.full, p.caption)} />
))}
<Lightbox src={src} alt={alt} onClose={close} />
</>
)
}Fully controlled:
const [open, setOpen] = useState(false)
<button onClick={() => setOpen(true)}>View</button>
<Lightbox open={open} src="/photo.jpg" alt="Photo" onClose={() => setOpen(false)} />Props
| prop | type | default | description |
| --- | --- | --- | --- |
| src | string \| null | — | Image to show. Falsy + no open ⇒ renders nothing. |
| alt | string | '' | Alt text / dialog label. |
| open | boolean | Boolean(src) | Explicit open state. |
| onClose | () => void | — | Required. Fired on ESC / backdrop / close button. |
| closeOnEsc | boolean | true | |
| closeOnBackdrop | boolean | true | |
| lockScroll | boolean | true | Lock body scroll while open. |
| zIndex | number | 9999 | Overlay z-index. |
| className | string | — | Extra class on the overlay for styling. |
| closeLabel | string | 'Close' | aria-label for the close button. |
| renderContent | ({ src, alt }) => ReactNode | — | Render custom content instead of the default <img>. |
Custom content
<Lightbox
src={src}
alt={alt}
onClose={close}
renderContent={({ src, alt }) => (
<figure onClick={(e) => e.stopPropagation()}>
<img src={src} alt={alt} style={{ maxWidth: '90vw', maxHeight: '80vh' }} />
<figcaption style={{ color: '#fff', textAlign: 'center' }}>{alt}</figcaption>
</figure>
)}
/>SSR
Safe with server rendering: it renders null until mounted in the browser
(it needs document for the portal), so it never breaks hydration.
License
MIT © ZachTRice
