Image Carousels and Galleries People Actually Use: A Guide for React
Galleries are where pretty and usable often split
A carousel is one of the easiest components to make beautiful and one of the easiest to make annoying. Cards fan out, photos tilt in 3D, a slider glides on its own. In a design review it looks great. Then a real person lands on the page, wants to see the third photo, and finds that it already slid away while they were reading the caption.
Galleries and carousels do a specific job: they let people browse a set of images at their own pace. Every decision about motion, layout and controls should serve that pace, not fight it. This guide walks through the choices that matter most when you build one in React and Tailwind, with examples from components you can drop into your own project.
First decide: grid, strip or stage
Most image components fall into three shapes, and picking the right one solves half the problems before you write any code.
A grid shows everything at once. It is the honest choice when people need to compare or scan, like a portfolio or a product range. Nothing is hidden, so nobody has to guess how many items there are. The Interactive Image Gallery takes this route and mixes photos with short text cards, then blurs the neighbours when you hover one, so focus moves without anything leaving the screen.
A strip is a row that moves, either on its own or when dragged. It works for mood and texture: a band of photos under a hero, a reel of past work. People are not expected to stop on any one image. The Image Auto Slider is a good example, a continuous loop with faded edges that hints at more without asking for attention.
A stage puts one item in front and the rest around it. Coverflow, fanned decks and orbital layouts belong here. They feel premium and they suit storytelling, but they hide most of the content at any given moment, so they need the best controls of the three.
If you are unsure, ask what someone should do after looking. If the answer is "pick one", a grid is usually kinder. If it is "get a feel", a strip is enough. If it is "go through them in order", a stage earns its complexity.
Let people drive
The single biggest complaint about carousels is losing control. A few rules keep people in the driver's seat:
- Autoplay should pause on hover, focus and interaction. If someone touches the carousel, they want to look. The Tilt Cascade Carousel stops its autoplay for good the moment you drag, press an arrow key or click a dot, and it also pauses when it scrolls off screen or the tab is hidden.
- Offer more than one way to move. Buttons for mouse users, swipe and drag for touch, arrow keys for keyboard users. A stage that only responds to drag is a trap on a desktop with a trackpad that scrolls the page instead.
- Show where people are. Dots, a counter like "03 / 08", or a thin progress bar. Without position, a carousel feels endless, and endless feels like work.
- Make the front item clickable, and the side items too. Clicking a card on the side should bring it forward. It is the most natural gesture there is, and many carousels ignore it.
The Coverflow Carousel covers all four: prev and next buttons, a horizontal drag with a swipe threshold, arrow keys when the region has focus, and a live region that announces "Slide 3 of 5" for screen readers.
Uncode UI
Build with AI, not against it.
Over 1,400 React and Tailwind components that run live in the browser, with a prompt ready to paste into Claude, Cursor or v0. Plus a community of people building real sites with AI.
Motion that explains instead of decorates
Good gallery motion tells people where things went. When a card moves from the side to the centre, the animation connects the two positions so nobody loses track. That is why springs work so well here: they start fast, settle gently and can be interrupted halfway without a jump.
Some details that make a real difference:
- Keep the main slide quick. Around a quarter to half a second for a single step is plenty. Longer than that and people start waiting on the interface instead of looking at the photo.
- Layer secondary motion behind the primary. In a fanned layout the cards can slide first and tilt a moment later. The small delay reads as weight and makes the whole thing feel physical rather than mechanical.
- Do not animate everything at once on load. A short stagger, like the arc in the Arc Gallery Hero, shows the shape of the layout and then gets out of the way.
- Respect reduced motion. When the system setting asks for less motion, swap springs and 3D rotation for a quick cross fade or an instant change. Framer Motion's
useReducedMotionhook makes this a one line check.
A useful test: turn the animation duration down to zero. If the gallery still makes sense, the motion was decoration on top of a solid layout. If it becomes confusing, the motion was doing real work and deserves care.
Hover is a preview, not a requirement
Many gallery effects live on hover: a card lifts, neighbours step aside, the others blur. These feel lovely with a mouse. On a phone, hover does not exist, and on a keyboard it only exists if you wire focus to the same state.
The Arch Gallery handles this simply: every card is focusable, and focus triggers the same lift as hover. The Card Hand Gallery goes further, with click, keyboard and a vertical flick to pull a card out of the hand, and it disables dragging on coarse pointers so a swipe over the fan still scrolls the page on a phone.
The rule of thumb: anything shown on hover should either be decorative or also reachable by tap and focus.
Images are most of the weight
A gallery is, by definition, a pile of images. The component code is rarely what slows the page down. A few habits keep it fast:
- Ask for the size you show. If a card is 300 pixels wide, a 4000 pixel original is wasted bandwidth. Most image CDNs, including Unsplash, accept a width parameter in the URL.
- Load what is near the front. Images more than a couple of steps away from the active slide can use
loading="lazy". The first ones should load normally so the stage is never empty. - Reserve space. Give cards a fixed size or an aspect ratio so the layout does not jump as photos arrive.
- Write real alt text. A carousel of travel photos with alt="image" tells a screen reader user nothing. If the image is purely decorative and the title is already announced elsewhere, an empty alt is better than a meaningless one.
For infinite strips, the common trick of duplicating the list to make a seamless loop doubles the number of images in the DOM. That is fine for eight photos and worth reconsidering for eighty.
Accessibility without a rewrite
You do not need a perfect implementation of every pattern to make a carousel usable. A handful of attributes and behaviours go a long way:
- Wrap it in an element with
role="region",aria-roledescription="carousel"and a cleararia-label. - Give each button a label: "Previous slide", "Next slide", "Go to slide 4".
- Announce changes politely with an
aria-live="polite"region, but not during autoplay, or it becomes noise. - Keep focus visible. A violet ring on a dark background is easy to see and fits most dark themes.
The Circular Carousel is a compact example: arrow keys move through the orbit, the dots act as tabs, and autoplay stops while the region has focus.
A short checklist before you ship
- Can someone stop the motion and look at one image for as long as they like?
- Can they reach every item with a mouse, a finger and a keyboard?
- Do they know how many items there are and where they are?
- Does it still make sense with reduced motion turned on?
- Are the images sized for the card, and is space reserved for them?
If the answer to all five is yes, the gallery is doing its job, and the fancy part, the tilt, the fan, the glow, becomes a bonus instead of an obstacle.
Every component mentioned here is in the Uncode UI catalog with a live preview. If you work with an AI editor, you can also connect the catalog to Claude Code, Cursor or Lovable and ask for a gallery by name, then adjust the motion and controls to fit your page.
Uncode UI
Build with AI, not against it.
Over 1,400 React and Tailwind components that run live in the browser, with a prompt ready to paste into Claude, Cursor or v0. Plus a community of people building real sites with AI.