Skip to main content
Back to blog list

Using scoll snap to create carousel

· 3 min read

Lately I have been playing a lot with css (and finally yes I get to do what I love) I was actually thinking of several applications of flex order property. Last usecase I found helps to solve a small accessibility issue in signup/NDA forms head here to see what it was.

This one tries to create a bare minimum infinite/circular carousel with as less as 70 lines of code all included HTML,CSS,JS

Its a carousel that has n number of slides and it keeps scrolling to right side (for LTR languages) and (n+1)th chilid is again 1st child.

So lets start

  • I will be using css flex, flex order, scroll-snap and little bit of plain JS to make our carousel autoscroll.
  • This is going to be a bare minimum carousel
<div class="carouselWrapper">
    <div class="carouselContainer">
        <div class="carouselItem">
            <img height="100px" width="100%" src="//via.placeholder.com/1000x100/FFFF00/000000/?text=Carousel+Item+21"
                alt="" />
        </div>
        <div class="carouselItem">
            <img height="100px" width="100%" src="//via.placeholder.com/1000x100/FF0000/FFFFFF/?text=Carousel+Item+22"
                alt="" />
        </div>
        <div class="carouselItem">
            <img height="100px" width="100%" src="//via.placeholder.com/1000x100/00FF00/000000?text=Carousel+Item+23"
                alt="" />
        </div>
    </div>
</div>

and here is the css

.carouselWrapper {
  position: relative;
}

.carouselContainer {
  display: flex;
  flex-wrap: nowrap;
  overflow-x: auto;
}
.carouselContainer .carouselItem {
  flex-grow: 0;
  flex-shrink: 0;
  max-width: 100%;
}

Check the codepen

You can get rid of that horizontal scroll bar using following css and add scroll snap to it

.carouselContainer {
  display: flex;
  flex-wrap: nowrap;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  overflow-x: auto;
  scrollbar-width: 0;
  scrollbar-color: transparent transparent;
}
.carouselContainer::-webkit-scrollbar {
  display: none;
}
.carouselContainer .carouselItem {
    flex-grow: 0;
    flex-shrink: 0;
    max-width: 100%;
    // we are telling browser to align each item centrally to
    // screen as it scrolls into viewport
    scroll-snap-align: center;
}

We have added following property scroll-snap-type: x mandatory; to carouselContainer class

here We are telling browser to apply scroll snap on horizontal axis and make it manadatory to scroll one item fully to snap behaviour to kick in. check more details here

We are also adding scroll-snap-align: center; property to carouselItem class

we are telling browser to align each item centrally to screen as it scrolls into viewport

Now lets add little bit of javascript

let index = 0;
const speed = 5;
const numberOfSlides = 3;
const carouselContainer = document.querySelector(".carouselContainer");
const carouselItemWidth = carouselContainer.scrollWidth / numberOfSlides;
setInterval(() => {
  carouselContainer.scrollBy(carouselItemWidth, 0);
  timeoutId = setTimeout(() => {
    index = index % numberOfSlides;
    let childToMove = carouselContainer.querySelectorAll(`.carouselItem`)[
      index
    ];
    // The line below move the item to end of carousel by
    // manipulating its flex order
    childToMove.style.order =
      childToMove.style.order && childToMove.style.order === 0
        ? 1
        : +childToMove.style.order + 1;
    index++;
    clearTimeout(timeoutId);
  }, 1000);
}, speed * 1000);

And woohoo our carousel is running

Let me know your thoughts on this.