Touch enabled minimalistic slider written in vanilla JavaScript
Hardware accelerated transitions
Usable as a jQuery plugin
Options for custom easing effects
infinite looping ~ carousel
No compromises for fallbacks
Written in ecmascript 6
Using webpack, babel & eslint for development
Download Hereor via cdn from cdnjs
<div class="slider js_slider">
<div class="frame js_frame">
<ul class="slides js_slides">
<li class="js_slide">1</li>
<li class="js_slide">2</li>
<li class="js_slide">3</li>
<li class="js_slide">4</li>
<li class="js_slide">5</li>
<li class="js_slide">6</li>
</ul>
</div>
<span class="js_prev prev">
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 501.5 501.5"><g><path fill="#2E435A" d="M302.67 90.877l55.77 55.508L254.575 250.75 358.44 355.116l-55.77 55.506L143.56 250.75z"/></g></svg>
</span>
<span class="js_next next">
<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 501.5 501.5"><g><path fill="#2E435A" d="M199.33 410.622l-55.77-55.508L247.425 250.75 143.56 146.384l55.77-55.507L358.44 250.75z"/></g></svg>
</span>
</div>
/**
* (optional) define here the style definitions which should be applied on the slider container
* e.g. width including further controls like arrows etc.
*/
.slider {}
.frame {
/**
* (optional) wrapper width, specifies width of the slider frame.
*/
width: 880px;
position: relative;
font-size: 0;
line-height: 0;
overflow: hidden;
white-space: nowrap;
}
.slides {
display: inline-block;
}
li {
position: relative;
display: inline-block;
/**
* (optional) if the content inside the slide element has a defined size.
*/
width: 880px;
}
.prev, .next {
position: absolute;
top: 50%;
margin-top: -25px;
display: block;
cursor: pointer;
}
.next {
right: 0;
}
.prev {
left: 0;
}
.next svg, .prev svg {
width: 25px;
}
document.addEventListener('DOMContentLoaded', function () {
var simple = document.querySelector('.js_simple');
lory(simple, {
infinite: 1
});
});
document.addEventListener('DOMContentLoaded', function () {
var simple_dots = document.querySelector('.js_simple_dots');
var dot_count = simple_dots.querySelectorAll('.js_slide').length;
var dot_container = simple_dots.querySelector('.js_dots');
var dot_list_item = document.createElement('li');
function handleDotEvent(e) {
if (e.type === 'before.lory.init') {
for (var i = 0, len = dot_count; i < len; i++) {
var clone = dot_list_item.cloneNode();
dot_container.appendChild(clone);
}
dot_container.childNodes[0].classList.add('active');
}
if (e.type === 'after.lory.init') {
for (var i = 0, len = dot_count; i < len; i++) {
dot_container.childNodes[i].addEventListener('click', function(e) {
dot_navigation_slider.slideTo(Array.prototype.indexOf.call(dot_container.childNodes, e.target));
});
}
}
if (e.type === 'after.lory.slide') {
for (var i = 0, len = dot_container.childNodes.length; i < len; i++) {
dot_container.childNodes[i].classList.remove('active');
}
dot_container.childNodes[e.detail.currentSlide - 1].classList.add('active');
}
if (e.type === 'on.lory.resize') {
for (var i = 0, len = dot_container.childNodes.length; i < len; i++) {
dot_container.childNodes[i].classList.remove('active');
}
dot_container.childNodes[0].classList.add('active');
}
}
simple_dots.addEventListener('before.lory.init', handleDotEvent);
simple_dots.addEventListener('after.lory.init', handleDotEvent);
simple_dots.addEventListener('after.lory.slide', handleDotEvent);
simple_dots.addEventListener('on.lory.resize', handleDotEvent);
var dot_navigation_slider = lory(simple_dots, {
infinite: 1,
enableMouseEvents: true
});
});
document.addEventListener('DOMContentLoaded', function () {
var percentage = document.querySelector('.js_percentage');
lory(percentage, {
infinite: 1
});
});
document.addEventListener('DOMContentLoaded', function () {
var rewind = document.querySelector('.js_rewind');
lory(rewind, {
rewind: true
});
});
document.addEventListener('DOMContentLoaded', function () {
var rewind_percentage = document.querySelector('.js_rewind_percentage');
lory(rewind_percentage, {
rewind: true
});
});
document.addEventListener('DOMContentLoaded', function () {
var variableWidth = document.querySelector('.js_variablewlidth');
lory(variableWidth, {
rewind: true
});
});
document.addEventListener('DOMContentLoaded', function () {
var multiSlides = document.querySelector('.js_multislides');
lory(multiSlides, {
infinite: 4,
slidesToScroll: 4
});
});
document.addEventListener('DOMContentLoaded', function () {
var ease = document.querySelector('.js_ease');
// http://easings.net/
lory(ease, {
infinite: 4,
slidesToScroll: 4,
slideSpeed: 1000,
ease: 'cubic-bezier(0.455, 0.03, 0.515, 0.955)'
});
});
document.addEventListener('DOMContentLoaded', function () {
var events = document.querySelector('.js_events');
function handleEvent(e) {
var newSpan = document.createElement('span');
var time = new Date();
time = time.getHours() + ':' + time.getMinutes() + ':' + time.getSeconds() + ',' + time.getMilliseconds();
var newContent = document.createTextNode('[' + time + '] Event dispatched: "' + e.type + '"');
newSpan.appendChild(newContent);
e.target.nextElementSibling.appendChild(newSpan);
}
events.addEventListener('before.lory.init', handleEvent);
events.addEventListener('after.lory.init', handleEvent);
events.addEventListener('before.lory.slide', handleEvent);
events.addEventListener('after.lory.slide', handleEvent);
events.addEventListener('before.lory.destroy', handleEvent);
events.addEventListener('after.lory.destroy', handleEvent);
events.addEventListener('on.lory.resize', handleEvent);
events.addEventListener('on.lory.touchend', handleEvent);
events.addEventListener('on.lory.touchmove', handleEvent);
events.addEventListener('on.lory.touchstart', handleEvent);
lory(events, {
infinite: 1
});
});
"use strict";
var lory = require('lory.js').lory;
document.addEventListener('DOMContentLoaded', function() {
var slider = document.querySelector('.js_slider');
lory(slider, {
// options going here
});
});
import {lory} from 'lory.js';
document.addEventListener('DOMContentLoaded', () => {
const slider = document.querySelector('.js_slider');
lory(slider, {
// options going here
});
});
<script src="js/jquery.lory.min.js"></script>
'use strict';
var $elements = $('.js_simple');
$(function() {
$elements.lory({
infinite: 1
});
$elements.data().lory.slideTo(4);
// $elements.data().lory.prev();
// $elements.data().lory.next();
});
// To install dev dependencies run:
yarn install
// To start the development server run:
yarn run dev
// To lint your code run:
yarn run lint
// To make a full new build run:
yarn run build
// To install dev dependencies run:
yarn install
// To start the karma tests locally run:
yarn run karma-local
prev: | slides to the previous slide | |
---|---|---|
next: | slides to the next slide | |
slideTo: | slides to the index given as an argument: (arguments: index {number}) | |
returnIndex: | returns the index of the current slide element | |
setup: | binds eventlisteners, merging default and user options, setup the slides based on DOM (called once during initialisation) | Call setup if DOM or user options have changed or eventlisteners needs to be rebinded. |
reset: | sets the slider back to the starting position and resets the current index (called on Resize event) | |
destroy: | unmount/destroy the instance of lory |
before.lory.init | fires before initialisation (first in setup function) | |
---|---|---|
after.lory.init | fires after initialisation (end of setup function) | |
before.lory.slide | arguments: currentSlide, nextSlide | fires before slide change |
after.lory.slide | arguments: currentSlide | fires after slide change |
before.lory.destroy | fires before the slider instance gets destroyed | |
after.lory.destroy | fires after the slider instance gets destroyed | |
on.lory.resize | fires on every resize event | |
on.lory.touchstart | fires on every slider touchstart event | |
on.lory.touchmove | fires on every slider touchmove event | |
on.lory.touchend | fires on every slider touchend event |