ARTICLE AD BOX
I'm working on a React hand-made horizontal carousel component but I'm struggling making an animation to slide the carousel when clicking the respective chevron image.
Do you have any idea how to do it?
This is my component.tsx?
import { useState } from 'react' // Styles import './Carousel.component.style.css' // Assets import leftsideChevron from '../../assets/images/LeftsideChevron.svg' import rightsideChevron from '../../assets/images/RightsideChevron.svg' const CarouselComponent = ({ itemsList, }: { itemsList: { title: string image: string }[] }) => { const [currentIndex, setCurrentIndex] = useState(0) const aux = 4 const onLeftClick = () => { if (currentIndex === 0) { return } console.log('currentIndex (left): ' + currentIndex) if (currentIndex <= aux) { setCurrentIndex(0) return } if (currentIndex - aux >= 0) { setCurrentIndex((value) => Math.max(0, value - aux)) } } const onRightClick = () => { if (currentIndex === itemsList.length) { return } console.log('currentIndex (right): ' + currentIndex) if (currentIndex + aux >= itemsList.length) { setCurrentIndex(itemsList.length) return } setCurrentIndex((value) => Math.min(value + aux, Math.max(0, itemsList.length - aux)), ) } return ( <div className="carouselContainer"> <img alt="leftside chevron" className="carouselLeftsideChevron" onClick={onLeftClick} src={leftsideChevron} /> <div className="itemsListContainer"> {itemsList.map((item, id) => { return ( <div className="itemContainer" key={item.title + id.toString()} > <img alt={item.image} src={item.image} /> <p>{item.title}</p> </div> ) })} </div> <img alt="rightside chevron" className="carouselRightsideChevron" onClick={onRightClick} src={rightsideChevron} /> </div> ) } export default CarouselComponentAnd this is my CSS file:
@import '../../assets/globals.css'; .carouselContainer { display: flex; justify-content: space-between; padding-top: 1em; } .itemsListContainer { display: flex; flex: 1 0 20%; overflow-x: auto; overflow: hidden; padding: 1em 0; scroll-snap-type: x mandatory; } .itemContainer { border-radius: 1em; box-shadow: 0 4px 20px rgba(0, 0, 0, 0.25); display: flex; gap: 1em; justify-content: center; margin: 0.2em 1em; min-width: 20%; scroll-margin-left: 1em; scroll-snap-align: start; max-width: 25%; } .itemContainer img { height: auto; width: 2.43rem; } .itemContainer p { font-family: Montserrat-Bold; font-size: 1.5rem; } .carouselRightsideChevron:hover, .carouselLeftsideChevron:hover { cursor: pointer; }Here is a screenshot for the component on screen:
What have I tried so far is to update my code to try this out:
const onLeftClick = () => { setCurrentIndex((prev) => Math.max(prev - aux, 0)) } const onRightClick = () => { setCurrentIndex((prev) => Math.min(prev + aux, itemsList.length - aux) ) } ... <div className="itemsViewport"> <div className="itemsListContainer" style={{ transform: `translateX(-${currentIndex * 100 / aux}%)`, }} > {itemsList.map((item, id) => ( <div className="itemContainer" key={item.title + id} > <img alt={item.image} src={item.image} /> <p>{item.title}</p> </div> ))} </div> </div>In combination with this CSS:
.itemsViewport { overflow: hidden; width: 100%; } .itemsListContainer { display: flex; transition: transform 0.4s ease-in-out; } .itemContainer { flex: 0 0 25%; text-align: center; }This wasn't a solution for my situation because it was not snaping my overflow-x to the very end of the carousel items. It ended up somewhere near the 60% of the overflow-x total width.

