Loading challenge...
Preparing the challenge details...
Loading challenge...
Preparing the challenge details...
Create an interactive image carousel in React with smooth slide transitions, navigation arrows, dot indicators, autoplay, and touch/swipe support for mobile devices.

Build an image carousel that displays one image at a time with smooth navigation, infinite looping, and optimal performance. The key challenges are implementing circular navigation logic and using CSS transforms to prevent layout thrashing.
The carousel uses a viewport + track pattern:
┌─────────────────────────────────────┐
│ [← Prev] ┌──────────┐ [Next →] │
│ │ Viewport │ │
│ │ (400px) │ │
│ └──────────┘ |
│ │ |
│ ┌────▼─────────────────┐ │
│ │ Track (flex container) |
│ │ [Img1][Img2][Img3]... |
│ └──────────────────────┘ |
└─────────────────────────────────────┘

overflow: hidden that shows only one imageThe implementation follows a controlled component pattern:
TSXcomponent.tsx1// Parent component manages state 2const [currentIndex, setCurrentIndex] = useState(0); 3 4// Child component receives props 5<ImageCarouselComponent 6 images={imageUrls} 7 onPrev={handlePrevClick} 8 onNext={handleNextClick} 9 currentIndex={currentIndex} 10/>
This separation allows:
currentIndex changes trigger updatesThe infinite loop is achieved using the modulo operator (%). This creates a circular index that wraps around at the boundaries.
TSXcomponent.tsx1function handleNextClick() { 2 setCurrentIndex((prevIndex) => (prevIndex + 1) % total); 3}
How it works:
prevIndex + 1: Move to next index% total: Wrap around when reaching the endExamples with 5 images (indices 0-4):
(0 + 1) % 5 = 1(1 + 1) % 5 = 2(2 + 1) % 5 = 3(3 + 1) % 5 = 4(4 + 1) % 5 = 0 (wraps to first)TSXcomponent.tsx1function handlePrevClick() { 2 setCurrentIndex((prevIndex) => (prevIndex - 1 + total) % total); 3}
Why (prevIndex - 1 + total)?
prevIndex - 1: Move to previous index+ total: Add total to handle negative values% total: Wrap aroundExamples with 5 images:
(0 - 1 + 5) % 5 = 4 (wraps to last)(1 - 1 + 5) % 5 = 0(2 - 1 + 5) % 5 = 1(3 - 1 + 5) % 5 = 2(4 - 1 + 5) % 5 = 3Why not just (prevIndex - 1) % total?
In JavaScript, -1 % 5 equals -1, not 4. Adding total first ensures we get a positive number before applying modulo:
(-1 + 5) % 5 = 4 % 5 = 4 ✓The carousel uses CSS transform: translateX() to slide images. This is crucial for performance.
TSXcomponent.tsx1transform: `translateX(-${(currentIndex * 100) / images.length}%)`
Breaking it down:
100 / images.length% of the track widthi, we need to shift the track left by i image widthscurrentIndex * (100 / images.length) = percentage to shiftExample with 5 images:
100 / 5 = 20% of tracktranslateX(-0%) → shows first imagetranslateX(-20%) → shows second imagetranslateX(-40%) → shows third imagetranslateX(-60%) → shows fourth imagetranslateX(-80%) → shows fifth imageGeneral formula:
translateX(-(currentIndex × 100) / images.length %)
Track width:
TSXcomponent.tsx1width: `${images.length * 100}%`
500% of viewport width100% of viewport (which is 20% of track)Individual image width:
TSXcomponent.tsx1width: `${100 / images.length}%`
100 / 5 = 20% of track widthVisual representation (5 images):
Viewport (400px):
┌────────────────────┐
│ │
└────────────────────┘
│
▼
Track (2000px = 500%):
┌────┬────┬────┬────┬────┐
│Img1│Img2│Img3│Img4│Img5│ Each: 400px (20% of 2000px)
└────┴────┴────┴────┴────┘
│
└─ translateX(-20%) shows Img2
Why transform?
transform and opacity are GPU-accelerated propertiesleft, top, or marginWhat happens with position changes:
CSSstyles.css1/* BAD: Triggers reflow */ 2.track { 3 left: -400px; /* Browser recalculates layout */ 4}
What happens with transform:
CSSstyles.css1/* GOOD: Only triggers repaint */ 2.track { 3 transform: translateX(-400px); /* Browser only updates visual */ 4}
All images are rendered in the DOM simultaneously:
TSXcomponent.tsx1{images.map((image, index) => ( 2 <img key={index} src={image} /> 3))}
Benefits:
Trade-off:
CSSstyles.css1.track { 2 transition: transform 0.5s ease-in-out; 3}
This provides smooth animation when currentIndex changes. The browser automatically animates the transform property between values.
TSXcomponent.tsx1<div className="viewport">
CSS:
CSSstyles.css1.viewport { 2 width: 400px; /* Fixed width */ 3 overflow: hidden; /* Hides images outside viewport */ 4}
The viewport acts as a "window" that shows only one image at a time.
TSXcomponent.tsx1<div className="track" style={{ transform: `translateX(...)` }}>
CSS:
CSSstyles.css1.track { 2 display: flex; /* Images side-by-side */ 3 transition: transform 0.5s ease-in-out; /* Smooth animation */ 4}
The track holds all images and slides horizontally based on currentIndex.
TSXcomponent.tsx1{images.map((image, index) => ( 2 <img 3 key={index} 4 src={image} 5 style={{ 6 width: `${100 / images.length}%`, 7 height: '300px', 8 objectFit: 'contain' 9 }} 10 /> 11))}
Each image:
100 / images.length% of track widthobjectFit: contain to maintain aspect ratioTo prevent loading all images at once, use native lazy loading:
TSXcomponent.tsx1<img 2 src={image} 3 loading={index === currentIndex || 4 index === currentIndex + 1 || 5 index === currentIndex - 1 ? "eager" : "lazy"} 6/>
This loads:
Set explicit dimensions to prevent Cumulative Layout Shift (CLS):
TSXcomponent.tsx1<img 2 src={image} 3 width={400} 4 height={300} 5 style={{ aspectRatio: '4/3' }} 6/>
(index + 1) % total for next and (index - 1 + total) % total for previoustranslateX(-(currentIndex × 100) / images.length %)images.length × 100% to fit all images100 / images.length% so images fit side-by-sidetransform instead of position changes to avoid reflowThe carousel is efficient, smooth, and works with any number of images because it's based on mathematical relationships rather than hardcoded values.
Goal: Implement a image carousel component that can be used to display a list of images.
Continue learning with these related challenges

Build a dynamic Tic Tac Toe game in React with customizable grid sizes, win detection algorithms, player turn management, and game reset functionality. Great for interviews.

Create an animated dice roller component in React with realistic rolling animations, random number generation, multiple dice support, and roll history tracking.

Build a fun Whack-a-Mole game in React with random mole spawning, click detection, score tracking, countdown timer, and increasing difficulty levels. Perfect for React practice.

Build a dynamic Tic Tac Toe game in React with customizable grid sizes, win detection algorithms, player turn management, and game reset functionality. Great for interviews.

Create an animated dice roller component in React with realistic rolling animations, random number generation, multiple dice support, and roll history tracking.

Build a fun Whack-a-Mole game in React with random mole spawning, click detection, score tracking, countdown timer, and increasing difficulty levels. Perfect for React practice.