Search code examples
javascriptcssreactjssplidejs

React Splide Carousel show peek of next image until you reach last slide


The issue is when reaching the last slide because I don't want it to loop. I want it to stop with no extra space or other image peeking out.

The best way I could find to achieve this was to use the padding: '5%' option which works, except on the last slide it will have the extra bit of padding which leaves a whitespace.

I tried finding a way to remove the padding once it reached the last slide, but the issue here is removing it causing all the images to get a bit larger and creates layout shift

I also tried setting perPage: 5.25 but this leads to weird behaviour when clicking to the next or prev slide.

Any help or ideas would be greatly appreciated.

Here's what I'm working with.

<Splide
      ref={slideRef}
      className="product-slider"
      hasTrack={false}
      options={{
        type: 'slide',
        perPage: 5,
        pagination: false,
        perMove: 2,
        wheel: true,
        padding: {right: '5%'},
      }}
    >
      <>
        <div className="splide__arrows">
          <button className="splide__arrow splide__arrow--prev">
            <IconChevron direction="right" />
          </button>
          <button className="splide__arrow splide__arrow--next">
            <IconChevron direction="right" />
          </button>
        </div>
        <SplideTrack>
          {slides.map((slide) => {
            return (
              <SplideSlide key={slide.id}>
               <Image />
              </SplideSlide>
            )
          })}
        </SplideTrack>
      </>
    </Splide>

Solution

  • I was able to achive what I wanted by adding a ref to Splide and using the on method to check when it was at the end of the slider.

    const slideRef = useRef(null)
    
      const [padding, setPadding] = useState({right: '5%', left: '0'})
    
      useEffect(() => {
        slideRef?.current?.splide?.on('moved', () => {
          const currentIndex = slideRef?.current?.splide.index
          const slideLength = slideRef?.current?.splide.length
    
          if (slideLength - currentIndex === 5) {
            setPadding({right: '0', left: '5%'})
          } else if (currentIndex === 0) {
            setPadding({right: '5%', left: '0'})
          }
        })
      }) 
    

    5 is the number I'm displaying perPage.

    I also added a class to the SplideTrack to help smooth the transitions when adding and removing the padding which gives it a nice bouncing effect.

    <SplideTrack className= 'splide-track-padding' /> 
    
    .splide-track-padding {
      transition: padding-left .3s ease-in-out, padding-right .3s ease-in-out;
    }