
A fancy, responsive image slider/carousel with pure JavaScript and CSS3 that automatically loops through a group of images with a fractal sliding animation.
How to use it:
Add images to the slider as these:
<div class="slider">
<div class="slider__inner">
<div class="slider__item">
<img class="slider__image" src="1.jpg" alt="Image 1">
<img class="slider__image" src="1.jpg" alt="Image 1">
<img class="slider__image" src="1.jpg" alt="Image 1">
<img class="slider__image" src="1.jpg" alt="Image 1">
<img class="slider__image" src="1.jpg" alt="Image 1">
</div>
<div class="slider__item">
<img class="slider__image" src="2.jpg" alt="Image 2">
<img class="slider__image" src="2.jpg" alt="Image 2">
<img class="slider__image" src="2.jpg" alt="Image 2">
<img class="slider__image" src="2.jpg" alt="Image 2">
<img class="slider__image" src="2.jpg" alt="Image 2">
</div>
<div class="slider__item">
<img class="slider__image" src="3.jpg" alt="Image 3">
<img class="slider__image" src="3.jpg" alt="Image 3">
<img class="slider__image" src="3.jpg" alt="Image 3">
<img class="slider__image" src="3.jpg" alt="Image 3">
<img class="slider__image" src="3.jpg" alt="Image 3">
</div>
</div>
</div>The main CSS/CSS3 styles.
.slider {
overflow: hidden;
}
.slider__inner {
display: flex;
flex-direction: row;
flex-wrap: nowrap;
transform: translateX(var(--slider-offset));
transition-property: transform;
transition-duration: var(--slider-time);
transition-timing-function: ease;
will-change: transform;
}
.slider__item {
flex: 1 0 100%;
box-sizing: border-box;
position: relative;
width: 100%;
height: auto;
}
.slider__image {
width: 100%;
height: auto;
transform: translateX(0);
animation-delay: var(--slide-distortion-delay), var(--slide-reset-delay);
animation-duration: var(--slide-distortion-time), var(--slide-reset-time);
animation-fill-mode: forwards, forwards;
animation-direction: normal, reverse;
}
.slider__image:not(:first-child) {
position: absolute;
top: 0;
left: 0;
}
.slider__image:nth-child(1) {
clip-path: inset(0 0 calc(var(--rate) * 4) 0);
}
.slider__image:nth-child(2) {
clip-path: inset(calc(var(--rate) * 1) 0 calc(var(--rate) * 3) 0);
}
.slider__image:nth-child(3) {
clip-path: inset(calc(var(--rate) * 2) 0 calc(var(--rate) * 2) 0);
}
.slider__image:nth-child(4) {
clip-path: inset(calc(var(--rate) * 3) 0 calc(var(--rate) * 1) 0);
}
.slider__image:nth-child(5) {
clip-path: inset(calc(var(--rate) * 4) 0 0 0);
}The primary CSS3 animations.
.slider__item--animating .slider__image:nth-child(1) {
animation-name: animation-1, animation-1;
}
.slider__item--animating .slider__image:nth-child(2) {
animation-name: animation-2, animation-2;
}
.slider__item--animating .slider__image:nth-child(3) {
animation-name: animation-3, animation-3;
}
.slider__item--animating .slider__image:nth-child(4) {
animation-name: animation-4, animation-4;
}
.slider__item--animating .slider__image:nth-child(5) {
animation-name: animation-5, animation-5;
}
@keyframes animation-1 {
from {
transform: translateX(0);
}
to {
// transform: translateX(-50px);
transform: translateX(-5vw);
}
}
@keyframes animation-2 {
from {
transform: translateX(0);
}
to {
transform: translateX(-3vw);
}
}
@keyframes animation-3 {
from {
transform: translateX(0);
}
to {
transform: translateX(1vw);
}
}
@keyframes animation-4 {
from {
transform: translateX(0);
}
to {
transform: translateX(3vw);
}
}
@keyframes animation-5 {
from {
transform: translateX(0);
}
to {
transform: translateX(-1vw);
}
}
@keyframes slide {
to {
transform: translateX(-100%);
}
}The main JavaScript to enable the slider.
const ANIMATING_CLASS = 'slider__item--animating';
const Slider = {
init() {
this.sliderEl = document.querySelector('.slider');
this.slideInnerEl = document.querySelector('.slider__inner');
this.sliderItemsEl = document.querySelectorAll('.slider__item');
this.offset = 0;
this.direction = 'left';
this.maxOffset = (this.sliderItemsEl.length - 1) * 100;
this.slideInnerEl.addEventListener('transitionend', this.onSliderTransitionEnd.bind(this));
setInterval(this.slide.bind(this), 3000);
},
slide() {
if (this.isMaxLeft()) {
this.direction = 'right';
} else if (this.isMaxRight()) {
this.direction = 'left';
}
this.moveSlider();
},
isMaxLeft() {
return this.offset <= -this.maxOffset;
},
isMaxRight() {
return this.offset >= 0;
},
getCurrentPage() {
if (this.offset < 0) {
return (this.offset * -1) / 100;
}
return this.offset / 100;
},
getSignal() {
return this.direction === 'left' ? -1 : 1;
},
onSliderTransitionEnd() {
const signal = this.getSignal();
const currentPage = this.getCurrentPage();
this.sliderItemsEl.forEach(element => element.classList.remove(ANIMATING_CLASS));
},
moveSlider() {
const signal = this.getSignal();
const currentPage = this.getCurrentPage();
this.offset = this.offset + (signal * 100);
this.sliderItemsEl[currentPage].classList.add(ANIMATING_CLASS);
this.sliderItemsEl[currentPage + (-1 * signal)].classList.add(ANIMATING_CLASS);
this.slideInnerEl.style.setProperty('--slider-offset', `${this.offset}%`);
}
};
const slider = Object.create(Slider);
slider.init();






