react-animated-gallery
v0.1.8
Published
React image gallery and carousel: three circular slots (left, center, right), smooth slot cycling, typed theme API, CSS animations. Works with Vite and Next.js (client-only).
Maintainers
Readme
react-animated-gallery
Animated React gallery for multi-image collections that renders exactly three images at a time, with smooth, low-distraction slot updates. react-animated-gallery is a TypeScript React component on npm: a circular three-slot image carousel with CSS-driven animation, optional theme overrides, and a bundled stylesheet (react-animated-gallery/style.css).
Links
| Resource | URL | | --- | --- | | npm package | react-animated-gallery | | Source & issues | github.com/ArmineInants/react-animated-gallery | | Live demo | react-animated-gallery.vercel.app |
Live demo

Why this gallery is unique
- Accepts multiple images and keeps the UI focused by showing only three slots at once (left, center, right).
- Uses slot-based replacement instead of page-like carousel jumps.
- Replaces only one slot per step, creating a smooth, subtle transition that is easy to follow.
- Keeps the center slot visually emphasized while cycling through all provided slides.
- Supports 3+ slides, loops continuously, and wraps from the last slide back to the first.
- Includes a strongly typed theme API with responsive (
*Laptop,*Tablet,*Mobile) overrides.
Install
npm install react-animated-galleryPeer dependencies:
react(18 or 19)react-dom(18 or 19)
Quick start
import { AnimatedGallery, type GallerySlide } from 'react-animated-gallery';
import 'react-animated-gallery/style.css';
const slides: GallerySlide[] = [
{ src: '/a.jpg', alt: 'A' },
{ src: '/b.jpg', alt: 'B' },
{ src: '/c.jpg', alt: 'C' },
{ src: '/d.jpg', alt: 'D' },
];
export function Hero() {
return <AnimatedGallery slides={slides} />;
}Next.js usage
If you see timing mismatch between CSS animation and JS updates in Next.js, render the component client-only with dynamic import:
'use client';
import dynamic from 'next/dynamic';
import 'react-animated-gallery/style.css';
const AnimatedGallery = dynamic(
() => import('react-animated-gallery').then((mod) => mod.AnimatedGallery),
{ ssr: false },
);Recommended in Next.js:
- Keep the gallery in a client component.
- Import
react-animated-gallery/style.cssat app-level (app/layout.tsx) or in your client entry where global CSS is allowed. - Use
ssr: falsefor the gallery component if hydration timing causes visual desync.
Props
| Prop | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| slides | GallerySlide[] | Yes | - | Slide data. Must contain at least 3 items. |
| theme | AnimatedGalleryTheme | No | DEFAULT_ANIMATED_GALLERY_THEME | Theme overrides for colors, timing, sizes, shadows, opacity, borders, border radius, z-index, and responsive variants. |
| className | string | No | undefined | Extra class name applied to the root gallery element. |
| style | React.CSSProperties | No | undefined | Inline styles for the root gallery element. |
| ...rest | HTMLAttributes<HTMLDivElement> | No | - | Any other valid div attributes (for example id, data-*, aria-*, onClick). |
GallerySlide
| Field | Type | Required | Description |
| --- | --- | --- | --- |
| src | string | Yes | Image URL. |
| srcSet | string | No | Responsive image sources. |
| sizes | string | No | Sizes hint used with srcSet. |
| alt | string | No | Alt text (defaults to ''). |
Theme customization
Import CSS once, then pass theme overrides:
<AnimatedGallery
slides={slides}
theme={{
colorAccent: '#00c4ff',
colorHighlight: '#0066ff',
duration: '8s',
borderRadius: '50%',
borderWidthMobile: '2px',
}}
/>The theme is typed as Partial<AnimatedGalleryThemeFull> (AnimatedGalleryTheme).
Theme keys and defaults
Base keys
| Key | Default | Description |
| --- | --- | --- |
| colorAccent | #ffc404 | Accent color for active borders and focus. |
| colorHighlight | #ffa016 | Background color for the center/active slot. |
| colorSlotMuted | rgba(255, 255, 255, 0.2) | Background for side slots. |
| colorBorderMuted | transparent | Border color for side slots. |
| shadowGlow | 0px 0px 50px rgb(255 196 4 / 70%), inset 0px 0px 0px 6px rgb(225 225 225 / 25%) | Shadow for the center/active slot. |
| shadowNone | none | Shadow for side slots. |
| duration | 10s | Duration of the CSS keyframe loop. |
| easing | ease-in-out | Easing function for the keyframe loop. |
| iteration | infinite | Iteration count for the keyframe loop. |
| imgBlockHeight | 220px | Overall gallery block height. |
| imgBlockWidth | 100% | Overall gallery block width. |
| slotSize | 170.43px | Diameter of the image circles. |
| offsetX | 128px | Horizontal offset of side slots from center. |
| scaleCenter | 1.29 | Scale factor applied to the center slot. |
| zBack | 1 | Z-index for side slots. |
| zFront | 6 | Z-index for the center slot. |
| opacityMuted | 0.4 | Opacity for side slots. |
| opacityActive | 1 | Opacity for the center slot. |
| borderWidth | 6px | Border width for all slots. |
| borderRadius | 50% | Border radius for slots (circle by default). |
Responsive keys
These override the matching base keys at breakpoints (Laptop, Tablet, Mobile):
| Key | Default |
| --- | --- |
| imgBlockWidthLaptop | 100% |
| imgBlockWidthTablet | 100% |
| imgBlockWidthMobile | 100% |
| slotSizeLaptop | 170px |
| slotSizeTablet | 170px |
| slotSizeMobile | 110px |
| offsetXLaptop | 128px |
| offsetXTablet | 128px |
| offsetXMobile | 75px |
| borderWidthLaptop | 6px |
| borderWidthTablet | 4px |
| borderWidthMobile | 2px |
Behavior notes
- At least 3 slides are required.
- The gallery renders 3 distinct images at a time (left/center/right).
- Slots update in sequence and loop forever, wrapping from the last slide back to the first.
- Only one slot is replaced on each step, so changes feel smooth and unobtrusive.
Local demo (repo only)
npm install
npm run demoThis starts the demo app from demo/. The published package ships dist/ only.
License
MIT
