Using scoll snap to create carousel
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
What do I mean by circular/infinite carousel?
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
Lets take a look at basic HTML and css for our 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.