📜 ⬆️ ⬇️

Carousel on Vanilla.JS

After reading this article, I decided to file my own carousel with blackjack and jQuery, although not, without it, because 2017 is not really needed either. Create a function that accepts an object with parameters and makes a slider. Some points will be omitted, such as: vendor prefixes, shift timer, etc.
The first thing we will do is markup for the carousel, on classes, and not id, so that you can use the same module several times on the page, and the specificity was not of the 3rd order.

HTML
<div class="wrap"> <div class="b-carousel js-carousel"> <button class="b-carousel__prev js-carousel__prev">Prev</button> <button class="b-carousel__next js-carousel__next">Next</button> <div class="b-carousel__wrap js-carousel__wrap"> <div class="b-carousel__item"> <img src="..." alt="" class="b-carousel__img"> </div> <div class="b-carousel__item"> <img src="..." alt="" class="b-carousel__img"> </div> <div class="b-carousel__item"> <img src="..." alt="" class="b-carousel__img"> </div> <div class="b-carousel__item"> <img src="..." alt="" class="b-carousel__img"> </div> </div> </div> </div> 


We have:


In CSS, we use the BEM notification, because we do not litter the global area. Let's make it slightly adaptive.

CSS
 .b-carousel { width: 100%; overflow: hidden; position: relative; box-sizing: border-box; border: 1px solid; } .b-carousel__prev, .b-carousel__next { position: absolute; top: 50%; left: 20px; width: 50px; height: 50px; background: #fff; transform: translateY(-50%) translateZ(0); cursor: pointer; text-indent: 100%; white-space: nowrap; overflow: hidden; z-index: 3; } .b-carousel__next { left: auto; right: 20px; } .b-carousel__wrap { display: flex; transition: transform .5s; will-change: transform; position: relative; z-index: 1; height: 100%; } .b-carousel__item { flex: 0 0 100%; overflow: hidden; display: flex; align-items: center; justify-content: center; } .b-carousel__img { width: 100%; display: block; } 


Transform: translateZ (0) for controls - a hack for putting them on a separate composite layer, so that when the container with the slides is moved, there are no buttons redrawing. And at a wrapper property of will-change. It is for the browser, so that it knows that some actions will take place with the block.
')
Let's start writing code. Create a function that accepts an object with parameters:

 function Carousel(setting) { /* Scope privates methods and properties */ let privates = {}; /* Privates properties */ privates.setting = setting; privates.sel = { "main": document.querySelector(privates.setting.main), "wrap": document.querySelector(privates.setting.wrap), "children": document.querySelector(privates.setting.wrap).children, "prev": document.querySelector(privates.setting.prev), "next": document.querySelector(privates.setting.next) }; privates.opt = { "position": 0, "max_position": document.querySelector(privates.setting.wrap).children.length }; // Control if(privates.sel.prev !== null) { privates.sel.prev.addEventListener('click', () => { this.prev_slide(); }); } if(privates.sel.next !== null) { privates.sel.next.addEventListener('click', () => { this.next_slide(); }); } } 

Management methods for the carousel:

 /* Public methods */ // Prev slide this.prev_slide = () => { --privates.opt.position; if(privates.opt.position < 0) { privates.sel.wrap.classList.add('s-notransition'); privates.opt.position = privates.opt.max_position - 1; } privates.sel.wrap.style["transform"] = `translateX(-${privates.opt.position}00%)`; }; // Next slide this.next_slide = () => { ++privates.opt.position; if(privates.opt.position >= privates.opt.max_position) { privates.opt.position = 0; } privates.sel.wrap.style["transform"] = `translateX(-${privates.opt.position}00%)`; }; 

The next_slide and prev_slide methods will move the wrapper using the transform, so that the block is not redrawn, and the animation takes place on the GPU.

Making a carousel:

 new Carousel({ "main": ".js-carousel", "wrap": ".js-carousel__wrap", "prev": ".js-carousel__prev", "next": ".js-carousel__next" }); 

If IE support is needed, then we replace the switch function with:
Come on, everybody knows it
If not everyone knows


It's all! Less code - less traffic (jQuery 3.2 ~ 85kB). Control over the parameters and can be used several times on the page.

Demo:



If you liked the article, then soon there will be a continuation with looping animation, touch-events and many more tasty buns!

Source: https://habr.com/ru/post/327246/


All Articles