Lightweight React lightbox component
npm install yet-another-react-lightbox-liteLightweight React lightbox component. This is a trimmed-down version of the
yet-another-react-lightbox
that provides essential lightbox features and slick UX with just 4.6KB bundle
size.



- Built for React: works with React 18+
- UX: supports keyboard, mouse, touchpad and touchscreen navigation
- Zoom: zoom is supported out of the box
- Performance: preloads a fixed number of images without compromising
performance or UX
- Responsive: responsive images with automatic resolution switching are
supported out of the box
- Customization: customize any UI element or add your own custom slides
- No bloat: supports only essential lightbox features
- TypeScript: type definitions come built-in in the package
!Yet Another React Lightbox Lite | Example
https://github.com/igordanchenko/yet-another-react-lightbox-lite
- Live demo -
https://stackblitz.com/edit/yet-another-react-lightbox-lite
- Examples -
https://stackblitz.com/edit/yet-another-react-lightbox-lite-examples
https://github.com/igordanchenko/yet-another-react-lightbox-lite/releases
- React 18+
- Node 18+
- modern ESM-compatible bundler
``shell`
npm install yet-another-react-lightbox-lite
`tsx
import { useState } from "react";
import Lightbox from "yet-another-react-lightbox-lite";
import "yet-another-react-lightbox-lite/styles.css";
export default function App() {
const [index, setIndex] = useState
return (
<>
{ src: "/image1.jpg" },
{ src: "/image2.jpg" },
{ src: "/image3.jpg" },
]}
index={index}
setIndex={setIndex}
/>
>
);
}
`
To utilize responsive images with automatic resolution switching, provide
srcset images in the slide srcSet array.
`tsx`
{
src: "/image1x3840.jpg",
srcSet: [
{ src: "/image1x320.jpg", width: 320, height: 213 },
{ src: "/image1x640.jpg", width: 640, height: 427 },
{ src: "/image1x1200.jpg", width: 1200, height: 800 },
{ src: "/image1x2048.jpg", width: 2048, height: 1365 },
{ src: "/image1x3840.jpg", width: 3840, height: 2560 },
],
},
// ...
]}
// ...
/>
If your project is based on Next.js, you may want to take
advantage of the
next/image
component. The next/image component provides a more efficient way to handle
images in your Next.js project. You can replace the standard elementnext/image
with with the following render.slide render function.
`tsx
slide: ({ slide, rect }) => {
const width =
slide.width && slide.height
? Math.round(
Math.min(rect.width, (rect.height / slide.height) * slide.width),
)
: rect.width;
const height =
slide.width && slide.height
? Math.round(
Math.min(rect.height, (rect.width / slide.width) * slide.height),
)
: rect.height;
return (
alt={slide.alt || ""}
width={width}
height={height}
loading="eager"
draggable={false}
blurDataURL={(slide as any).blurDataURL}
style={{
minWidth: 0,
minHeight: 0,
maxWidth: "100%",
maxHeight: "100%",
objectFit: "contain",
}}
/>
);
},
}}
// ...
/>
`
Yet Another React Lightbox Lite comes with CSS stylesheet that needs to be
imported in your app.
`tsx`
import "yet-another-react-lightbox-lite/styles.css";
The lightbox component accepts the following props.
Type: Slide[]
An array of slides to display in the lightbox. This prop is required. By
default, the lightbox supports only image slides. You can add support for custom
slides through a custom render function (see example below).
Image slide props:
- src - image source (required)alt
- - image alt attribute
Type: number | undefined
Current slide index. This prop is required.
Type: (index: number | undefined) => void
A callback to update current slide index state. This prop is required.
Type: keyof Labels
Custom UI labels / translations.
`tsx`
Previous: t("Previous"),
Next: t("Next"),
Close: t("Close"),
}}
// ...
/>
Type: object
Toolbar settings.
- buttons - custom toolbar buttons (type: ReactNode[])fixed
- - if true, the toolbar is positioned statically above the carousel
Usage example:
`tsx`
fixed: true,
buttons: [
type="button"
className="yarll__button"
onClick={() => {
// ...
}}
>
,
],
}}
// ...
/>
Type: object
Carousel settings.
- preload - the lightbox preloads (2 * preload + 1) slides (default: 2)imageProps
- - custom image slide attributes
Usage example:
`tsx`
preload: 5,
imageProps: { crossOrigin: "anonymous" },
}}
// ...
/>
Type: object
Controller settings.
- closeOnPullUp - if true, close the lightbox on pull-up gesture (default:true
)closeOnPullDown
- - if true, close the lightbox on pull-down gesturetrue
(default: )closeOnBackdropClick
- - if true, close the lightbox when the backdrop istrue
clicked (default: )
Usage example:
`tsx`
closeOnPullUp: false,
closeOnPullDown: false,
closeOnBackdropClick: false,
}}
// ...
/>
Type: object
An object providing custom render functions.
`tsx`
slide: ({ slide, rect, zoom, current }) => (
),
slideHeader: ({ slide, rect, zoom, current }) => (
),
slideFooter: ({ slide, rect, zoom, current }) => (
),
controls: () =>
iconPrev: () =>
iconNext: () =>
iconClose: () =>
}}
// ...
/>
#### slide: ({ slide, rect, zoom, current }) => ReactNode
Render custom slide type, or override the default image slide implementation.
Parameters:
- slide - slide object (type: Slide)rect
- - slide rect size (type: Rect)zoom
- - current zoom level (type: number)current
- - if true, the slide is the current slide in the viewport (type:boolean
)
#### slideHeader: ({ slide, rect, zoom, current }) => ReactNode
Render custom elements above each slide.
#### slideFooter: ({ slide, rect, zoom, current }) => ReactNode
Render custom elements below or over each slide. By default, the content is
rendered right under the slide. Alternatively, you can use
position: "absolute" to position the extra elements relative to the slide.
For example, you can use the slideFooter render function to add slides
descriptions.
`tsx`
slideFooter: ({ slide }) => (
{slide.description}
),
}}
// ...
/>
#### controls: () => ReactNode
Render custom controls or additional elements in the lightbox (use absolute
positioning).
For example, you can use the render.controls render function to implement
slides counter.
`tsx`
controls: () =>
index !== undefined && (
{index + 1} of {slides.length}
),
}}
// ...
/>
#### iconPrev: () => ReactNode
Render custom Previous icon.
#### iconNext: () => ReactNode
Render custom Next icon.
#### iconClose: () => ReactNode
Render custom Close icon.
Type: { [key in Slot]?: SlotCSSProperties }
Customization slots styles allow you to specify custom CSS styles or override
--yarll__* CSS variables by passing your custom styles through to the
corresponding lightbox elements.
Supported customization slots:
- portal - lightbox portal (root)carousel
- - lightbox carouselslide
- - lightbox slideimage
- - lightbox slide imagetoolbar
- - lightbox toolbarbutton
- - lightbox buttonicon
- - lightbox icon
Usage example:
`tsx`
portal: { "--yarll__backdrop_color": "rgba(0, 0, 0, 0.6)" },
}}
// ...
/>
Type: string
CSS class of the lightbox root element. You can use this class name to provide
module-scoped style overrides.
Type: object
Zoom settings.
- disabled - disable zoom on image slidessupports
- - zoom-enabled custom slide types
Usage example:
`tsx`
// ...
/>
You can add custom slide attributes with the following module augmentation.
`tsx`
declare module "yet-another-react-lightbox-lite" {
interface GenericSlide {
description?: string;
}
}
You can add custom slide types through module augmentation and render them with
the render.slide render function.
Here is an example demonstrating video slides implementation.
`tsx
declare module "yet-another-react-lightbox-lite" {
interface SlideVideo extends GenericSlide {
type: "video";
src: string;
poster: string;
width: number;
height: number;
}
interface SlideTypes {
video: SlideVideo;
}
}
// ...
{
type: "video",
src: "/media/video.mp4",
poster: "/media/poster.jpg",
width: 1280,
height: 720,
},
]}
render={{
slide: ({ slide }) =>
slide.type === "video" ? (
controls
playsInline
poster={slide.poster}
width={slide.width}
height={slide.height}
style={{ maxWidth: "100%", maxHeight: "100%" }}
>
) : undefined,
}}
// ...
/>;
`
`tsx
// Lightbox.tsx
import LightboxComponent, {
LightboxProps,
} from "yet-another-react-lightbox-lite";
import "yet-another-react-lightbox-lite/styles.css";
export default function Lightbox(props: LightboxProps) {
return
}
`
`tsx
// App.tsx
import { lazy, Suspense, useState } from "react";
import slides from "./slides";
const Lightbox = lazy(() => import("./Lightbox"));
export default function App() {
const [index, setIndex] = useState
return (
<>
{index !== undefined && (
)}
>
);
}
`
By default, the lightbox hides the browser window scrollbar and prevents
document
from scrolling underneath the lightbox by assigning the
height: 100%; overflow: hidden; styles to the document element.If this behavior causes undesired side effects in your case, and you prefer not
to use this feature, you can turn it off by assigning the
yarll__no_scroll_lock class to the lightbox.`tsx
className="yarll__no_scroll_lock"
// ...
/>
`However, if you keep the body scroll lock feature on, you may notice a visual
layout shift of some fixed-positioned page elements when the lightbox opens. To
address this, you can assign the
yarll__fixed CSS class to your
fixed-positioned elements to keep them in place. Please note that the
fixed-positioned element container should not have its own border or padding
styles. If that's the case, you can always add an extra wrapper that just
defines the fixed position without visual styles.Text Selection
The lightbox is rendered with the
user-select: none CSS style. If you'd like
to make some of your custom elements user-selectable, use the
yarll__selectable CSS class. This class sets the user-select: text style and
turns off click-and-drag slide navigation, likely interfering with text
selection UX.Hooks
The library exports the following hooks that you may find helpful in customizing
lightbox functionality.
$3
You can use the
useZoom hook to build your custom zoom controls.`tsx
import { useZoom } from "yet-another-react-lightbox-lite";
`The hook provides an object with the following props:
-
rect - slide rect
- zoom - current zoom level (numeric value between 1 and 8)
- maxZoom - maximum zoom level (1 if zoom is not supported on the current
slide)
- offsetX - horizontal slide position offset
- offsetY - vertical slide position offset
- changeZoom - change zoom level
- changeOffsets` - change position offsetsMIT © 2024 Igor Danchenko