Author: | Manuel Madeira |
---|---|
Views Total: | 381 views |
Official Page: | Go to website |
Last Update: | March 7, 2018 |
License: | MIT |
Preview:

Description:
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();