JSFiddle - React, Tailwind, and code Playground
by BurpmanJunior
HTML
<div class="ec-carousel" id="demo">
<div>
<ul>
<li><a href="#!"><img src="https://images.unsplash.com/photo-1421987392252-38a07781c07e?crop=entropy&fit=crop&fm=jpg&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=500&h=300" /></a></li>
<li><a href="#!"><img src="https://images.unsplash.com/photo-1433190152045-5a94184895da?crop=entropy&fit=crop&fm=jpg&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=500&h=300" /></a></li>
<li><a href="#!"><img src="https://images.unsplash.com/photo-1432383079404-c66efb4828a3?crop=entropy&fit=crop&fm=jpg&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=500&h=300" /></a></li>
<li><a href="#!"><img src="https://images.unsplash.com/photo-1452110040644-6751c0c95836?crop=entropy&fit=crop&fm=jpg&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=500&h=400" /></a></li>
<li><a href="#!"><img src="https://images.unsplash.com/photo-1453106037972-08fbfe790762?crop=entropy&fit=crop&fm=jpg&ixjsv=2.1.0&ixlib=rb-0.3.5&q=80&w=500&h=300" /></a></li>
</ul>
</div>
</div>
SCSS
*,*:before,*:after{
box-sizing: border-box;
}
body{
margin: 0;
}
.ec-carousel{
ul{
margin: 0;
padding: 8px;
li{
list-style-type: none;
padding: 8px;
img{
display: block;
max-width: 100%;
margin: 0 auto;
}
}
}
// Initialized
&.ec-carousel-init{
position: relative;
.ec-carousel-track{
position: relative;
overflow: hidden;
width: calc(100% - (16px + (32px * 2)));
margin: 0 auto;
ul{
display: table;
padding: 0;
position: relative;
transition: transform 300ms;
li{
display: table-cell;
vertical-align: middle;
}
}
}
button{
display: block;
background: rgba(255, 255, 255, 0);
color: #353535;
border: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
.ec-carousel__prev{
left: 0;
&:after{
content: '\25C0';
}
}
.ec-carousel__next{
right: 0;
&:after{
content: '\25B6';
}
}
}
}
JavaScript
/**
* EC Carousel
* @param {object} elem DOM Element
* @return {object} Self
*/
var ecCarousel = function(elem){
this.BREAKPOINT = 800;
this.WRAP = elem;
this.TRACK = elem.querySelector('div');
this.TRACK_INNER = this.TRACK.querySelector('ul');
this.IMAGES = elem.querySelectorAll('li');
if(this.IMAGES.length < 1){ return false; }
this.CURRENT = 0;
this.MAX_I = this.IMAGES.length - 1;
this.COLS = 1;
this.CONTROLS = {
prev: null,
next: null
}
// Init
var _t = this;
this.TRACK.className += ' ec-carousel-track';
this.WRAP.className += ' ec-carousel-init';
Array.prototype.forEach.call(_t.IMAGES, function(el){
el.style.width = (100 / (_t.MAX_I + 1)) + '%';
});
this.buildControls();
window.addEventListener('resize', function(){
_t.updateDimensions();
});
this.updateDimensions();
this.updateTrack();
return this;
}
/**
* Renders and binds controls
*/
ecCarousel.prototype.buildControls = function(){
var _t = this,
prevBtn,
nextBtn;
// Prev
prevBtn = document.createElement('button');
prevBtn.className = 'ec-carousel__prev';
prevBtn.addEventListener('click', function(e){
e.preventDefault();
_t.prev();
});
this.CONTROLS.prev = this.WRAP.appendChild(prevBtn);
// Next
nextBtn = document.createElement('button');
nextBtn.className = 'ec-carousel__next';
nextBtn.addEventListener('click', function(e){
e.preventDefault();
_t.next();
});
this.CONTROLS.next = this.WRAP.appendChild(nextBtn);
}
/**
* Next slide
* @return {boolean}
*/
ecCarousel.prototype.next = function(){
if(this.CURRENT < this.MAX_I){
this.CURRENT++;
this.updateTrack();
return true;
}
return false;
}
/**
* Prev slide
* @return {boolean}
*/
ecCarousel.prototype.prev = function(){
if(this.CURRENT > 0){
this.CURRENT--;
this.updateTrack();
return true;
}
return false;
}
/**
* Update track and controls
*/
ecCarousel.prototype.updateTrack =...