About Kineto
Kineto is an open source JavaScript library for building carousels on websites. It aims to cover every essential feature of a carousel while staying simple and intuitive for integration.
- No extra dependencies required.
- Works in all major browsers and IE9+.
- Control over size, spacing, direction of the slides.
- Infinite loop without duplicate slides.
- Add or remove slides dynamically.
- Custom speed and easing of the movement.
- Navigation with touch and mouse swipe.
- Automatic rotation & sync with other Kineto instances.
- And many more.
Get started
Please download the latest version of Kineto. Ready-to-use
resources are located in /dist
folder.
Embed Kineto assets
Insert the CSS and JS files into your HTML.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="kineto.css" />
</head>
<body>
<script src="kineto.js"></script>
</body>
</html>
- The CSS file contains opinionated theme for Kineto's submodules. You don't need to include it if you are going to create your own look and feel.
-
The JS file is placed at the end of
body
element for improved performance.
Create HTML structure
You only need to have a container holding your content slides as
direct children elements. class
and accessibility
attributes will be automatically added once you enable Kineto.
<div>
<div>Slide 1</div>
<div>Slide 2</div>
<div>Slide 3</div>
</div>
Initialize Kineto with JavaScript
Once
DOM is ready, you can now initialize Kineto with
Kineto.create()
method. Below is an example:
Kineto.create('#carousel', { pagination: true });
Kineto is applied to all elements matching the selector provided. To control only a specific instance, we recommend you to use either a unique selector or an element object instead the selector.
Demo
Default
Kineto.create('#carousel');
Number of visible slides
Kineto.create('#carousel', { perView: 2 });
Margin between slides
Kineto.create('#carousel', { margin: 40 });
Vertical direction
Kineto.create('#carousel', { mode: 'vertical' });
Infinite loop
Kineto.create('#carousel', { loop: true });
Adaptive Height
Kineto.create('#carousel', { height: 'adaptive' });
Equal Height
Kineto.create('#carousel', { height: 'equal' });
Move by 2
Kineto.create('#carousel', { moveBy: 2 });
Movement speed
Kineto.create('#carousel', { speed: 1000 });
Animation easing
Kineto.create('#carousel', { easing: 'easeInOutBack' });
Kineto.create('#carousel', { easing: [0.2, 2, 0.3, 0.8] });
Move to clicked slide
Kineto.create('#carousel', { moveOnClick: true });
Auto playing
Kineto.create('#carousel', { stream: true });
Navigation components
Kineto.create('#carousel', {
arrows: true,
arrowTemplate: ['←', '→'],
count: true,
countTemplate: '<em class="current">{{current}}</em> / {{total}}',
pagination: true,
paginationTemplate: '{{index}}',
});
Block swiping beyond edges
Kineto.create('#carousel', { swipeEdgeBounce: false });
Mouse wheel
Kineto.create('#carousel', { wheel: true });
Allow only 1 wheel per second
Kineto.create('#carousel', { wheel: true, wheelThrottle: 1000 });
Scroll blocked after hitting edges
Kineto.create('#carousel', { wheelEdgeRelease: false, mode: 'vertical' });
Use percentage values in CSS
Setting responsive
option make carousels reload on
viewport size changed. If you want them to scale with its
container without triggering reload,
usePercent
will come in handy. (Resize your browser
window to observe the difference.)
Kineto.create('#carousel', { usePercent: true, responsive: false });
Responsive
Kineto.create('#carousel', {
// 0 ~ 599
perView: 1,
responsive: {
// 600 ~ 799
600: {
perView: 1.5,
margin: 20,
},
// 800 ~
800: {
perView: 2,
margin: 30,
},
}
});
The responsive
option follows mobile-first approach
— it is processed from the smallest resolution to the largest.
Using desktop-first responsiveMode
can reverse the
order of processing.
Kineto.create('#carousel', {
// 801 ~
perView: 2,
responsive: {
// 601 ~ 800
800: {
perView: 1.5,
margin: 30,
},
// 0 ~ 600
600: {
perView: 1,
margin: 20,
},
},
responsiveMode: 'desktop-first'
});
Sync between instances
// Assign same `syncId` to carousels to get in sync.
Kineto.create('#carousel1', {
syncId: 'gallery',
loop: true,
stream: true,
});
Kineto.create('#carousel2', {
syncId: 'gallery',
perView: 3,
loop: true,
pagination: false,
});
Kineto.create('#carousel3', {
syncId: 'gallery',
perView: 5,
align: 'justify',
arrows: false,
pagination: false,
});
Options
Kineto.create
method takes 2 parameters — you can
configure Kineto by passing an object containing desired
options.
Kineto.create(container, options);
Here's the summarized version of default options.
{
mode: 'horizontal',
align: 'center',
perView: 'auto',
height: 'auto',
margin: 10,
loop: false,
startAt: 0,
moveBy: 1,
speed: 600,
easing: [0, 0, 0.2, 1],
moveOnClick: false,
waitAnimation: false,
stream: false,
streamEvery: 3000,
streamRewind: true,
pauseOnFocus: true,
pauseOnHover: false,
syncId: null,
arrows: true,
arrowsInto: null,
arrowTemplate: null,
count: false,
countInto: null,
countTemplate: null,
pagination: true,
paginationInto: null,
paginationTemplate: null,
touchSwipe: true,
mouseSwipe: true,
swipeThreshold: 3,
swipeMultiplier: 1,
swipeEdgeBounce: true,
swipeEdgeFriction: 0.8,
wheel: false,
wheelTarget: null,
wheelThrottle: 'auto',
wheelEdgeRelease: true,
aria: true,
cssPrecision: 3,
usePercent: false,
responsive: true,
responsiveDelay: 100,
responsiveMode: 'mobile-first',
}
Layout
Key | Type | Default | Description |
---|---|---|---|
mode |
'horizontal' 'vertical'
|
'horizontal' |
The direction of the content flow. (The option is named so to prepare for the addition of new modes in the future.) |
align |
'center' 'start' 'end' 'justify'
|
'center' |
The alignment of slides.
|
perView |
number 'auto'
|
'auto' |
Number of slides to show per frame. Floats are accepted. |
height |
'auto' 'adaptive' 'equal'
|
'auto' |
The way the carousel handles its height.
|
margin | number |
10 |
Distance (in pixel) between slides. |
loop | boolean |
false |
Wrap around to the other end on edges to allow infinite navigation. |
startAt | number |
0 |
Zero-based index of the slide to be shown on initialization. |
Movement
Options related to movements of the carousel. They do not affect swipe movements.
Key | Type | Default | Description |
---|---|---|---|
moveBy | number |
1 |
Number of slides to pass when moving. |
speed | number |
600 |
Duration of movements. |
easing | string number[] |
[
|
Easing curve of movements. You can enter either a CSS-like easing function name listed below, or an array of 4 besier points.
|
moveOnClick | boolean |
false |
Move to clicked slide. |
waitAnimation | boolean |
false |
Prevent movements from being fired while an animation being played. |
Streaming
Key | Type | Default | Description |
---|---|---|---|
stream | boolean |
false |
Automatically move to next slide every N milliseconds. Kineto will pause streaming when:
|
streamEvery | number |
3000 |
Time gap (in milliseconds) between each stream tick. |
streamRewind | boolean |
true |
Redirect the stream to the first slide after hitting the last slide. |
pauseOnFocus | boolean |
true |
Pause the streaming while slide is focused. |
pauseOnHover | boolean |
false |
Pause the streaming while pointer cursor is on. |
syncId | string |
null |
Synchronize other kineto instances with same
Setting |
Addons
Key | Type | Default | Description |
---|---|---|---|
arrows | boolean |
true |
Add previous & next buttons. |
arrowsInto | string HTMLElement |
null |
Specify the container element for the arrow buttons. Accepts either an element selector or a element object. |
arrowsTemplate | [string, string] |
null |
Array of strings representing content HTML for the arrow buttons.
e.g.
|
count | boolean |
true |
Add a fraction-style pagination. |
countInto | string |
null |
Specify the container element for the count component. Accepts either an element selector or a element object. |
countTemplate | string |
null |
String representing content HTML for the count component.
e.g.
|
pagination | boolean |
true |
Add page indicator buttons. |
paginationInto | string |
null |
Specify the container element for the pagination. Accepts either an element selector or a element object. |
paginationTemplate | string |
null |
String representing content HTML for the count component.
e.g.
|
Swipe
Key | Type | Default | Description |
---|---|---|---|
touchSwipe | boolean |
true |
Allow scrolling by touch drag. |
mouseSwipe | boolean |
true |
Allow scrolling by mouse drag. |
swipeThreshold | number |
3 |
Amount of pixels in pixel to skip before drag movement starts. |
swipeMultiplier | number |
1 |
Amplify swipe movement by this value. |
swipeEdgeBounce | boolean |
true |
Apply elastic rebound motion on both edges. Has no
effect when loop: true
|
swipeEdgeFriction | boolean |
0.8 |
Reduce the swipe movement beyond both edges. Any number between 0 ~ 1(inclusive) is accepted. |
Mouse wheel
Key | Type | Default | Description |
---|---|---|---|
wheel | boolean |
false |
Allow scrolling by mouse wheel. |
wheelTarget | string |
null |
Element that receives the mouse wheel. Fallback to the element wrapper slides. |
wheelThrottle |
number 'auto'
|
'auto' |
Time (in miliseconds) during which successive scroll attempts should be ignored. |
wheelEdgeRelease |
boolean
|
true |
Unblock scroll when the scroll reaches the last slide in the scrolling direction. Especially useful when the carousel's content flow is parallrel to the document's scroll direction. |
Miscellaneous
Key | Type | Default | Description |
---|---|---|---|
aria | boolean |
true |
Add & update accessibility attributes. |
cssPrecision | number |
3 |
The precision for CSS values that include numbers.
Setting it to 0 may fix
issues with half-pixel rendering.
|
usePercent | boolean |
false |
Use percentage for CSS values that include numbers. Useful if you want your carousel to scale with its container without reloading. |
Responsive
Key | Type | Default | Description |
---|---|---|---|
responsive | boolean object |
true |
Switch kineto settings based on viewport width. The value has to be an object type: child keys stand for viewport range, child values kineto settings matching the range.
|
responsiveDelay | number |
100 |
Time delay (in milliseconds) before responding to the viewport changes. |
responsiveMode |
'mobile-first' 'desktop-first'
|
'mobile-first' |
The strategy used to parse
|
ClassNames
The plugin dispose Kineto.setClassFormat()
to
enable the customization of how CSS classes are formatted, to
help you stay constant in class naming throughout the project.
You can either provide a built-in preset name, or a custom formatter created on your own.
kebabcase (default)
Join words with dash(-), seperating each kind of identifier for higher modularity.
-
'kineto'
: The container. -
'kineto-animating'
: Dynamically added class to the container during animations. -
'kineto-slide'
: The slides inside the container. -
'kineto-slide kineto-visible kineto-active'
: The currently active and visible slide.
Kineto.setClassFormat('kebabcase');
BEM
Follow BEM strategy for class naming. BEM helps in reducing specificity down to a minimum, and writing codes with high readability. Here's some examples how classes will look like:
-
'kineto'
: The container. -
'kineto--animating'
: Dynamically added class to the container during animations. -
'kineto__slide'
: The slides inside the container. -
'kineto__slide--visible kineto__slide--active'
: The currently active and visible slide.
Kineto.setClassFormat('BEM');
Custom formatter function
You can make your own formatter using the raw data passed as parameters. The formatter function will receive block, element, modifier according to BEM rules.
-
@param
blockstring
-
@param
elementsstring[]
-
@param
modifierstring
Kineto.setClassFormat(function(block, elements, modifier) {
var output = capitalize(block);
if (elements.length) {
output += '_' + elements.join('_');
}
if (modifier) {
output += '-' + modifier;
}
return output;
});
Methods
The plugin dispose public methods in its namespace. Most of them require follow next syntax:
Kineto.method(container, [, arguments...]);
- container — The selector for the container(s) to execute the command onto; a HTMLElement, a NodeList, a HTMLCollection, or an Array of HTMLElement can be used alternatively.
- arguments — Extra parameters to pass to the method.
.setDefaults()
Set default options for all Kineto instance to be created after this line of code. Does not require container element as parameter.
-
@param
optionsobject
— Subset of Kineto options to use as base options.
// Use next settings for all Kineto instances after this line.
Kineto.setDefaults({
stream: true,
streamEvery: 4000,
});
.setClassFormat()
Set CSS class formatting rules for all Kineto instance to be created after this line of code.
-
@param
formatstring | function
— A class naming preset or a custom formatter function.
Read ClassNames section for the details.
// Use BEM-based classes for all Kineto instances after this line.
Kineto.setClassFormat('BEM');
.create()
Instantiate Kineto on elements that match the selector passed.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
optionsobject
— Kineto options. See Options for details.
// Seletor (single or multiple elements)
Kineto.create('.carousel');
// HTMLElement (single element)
var element = document.querySelector('.carousel');
Kineto.create(element);
// NodeList (multiple elements)
var nodelist = document.querySelectorAll('.carousel');
Kineto.create(nodelist);
// HTMLCollection (multiple elements)
var collection = document.getElementsByClassName('.carousel');
Kineto.create(collection);
// Array of HTMLElement (multiple elements)
var elementArray = [].slice.call(document.querySelectorAll('.carousel'));
Kineto.create(elementArray);
// Using jQuery
var fromJquery = $('.carousel').get();
Kineto.create(fromJquery);
.goTo()
Move to a specific slide that matches the index passed. Negative index will count from the end.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
indexnumber
— The index of the destination slide.
// Go to the 3rd slide.
Kineto.goTo('#carousel', 2);
// Go to the last slide.
Kineto.goTo('#carousel', -1);
.next()
Go to the next slide.
-
@param
containerstring | HTMLElement
— The container element or its selector.
.prev()
Go to the previous slide.
-
@param
containerstring | HTMLElement
— The container element or its selector.
.refresh()
Force Kineto reload and recalculate layout. This is helpful when manipulating slide content that affects the layout.
-
@param
containerstring | HTMLElement
— The container element or its selector.
.addSlide()
Add new slide(s) to an existing carousel. Negative index will select from the end. If inserting position is not specified, add the slide at the end.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
contentsstring | string[]
— HTML string(s) representing the content the new slide(s). -
@param
positionnumber
— Optional. The position where the new slide(s) should be inserted at.
// Add 1 slide at the end
Kineto.addSlide('#carousel', 'New slide');
// Add 1 slide after the 2nd slide
Kineto.addSlide('#carousel', 'New slide', 1);
// Add 2 slides at the end
Kineto.addSlide('#carousel', ['New slide', 'Newer slide']);
// Add 2 slides after the 2nd last slide
Kineto.addSlide('#carousel', ['New slide', 'Newer slide'], -2);
.removeSlide()
Remove existing slide at a specific position. If removing position is not specified, remove the last slide.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
contentsstring | string[]
— HTML string(s) representing the content the new slide(s).
// Remove last slide
Kineto.removeSlide('#carousel');
// Remove 2nd slide
Kineto.removeSlide('#carousel', 1);
// Remove 2nd last slides
Kineto.removeSlide('#carousel', -2);
// Remove last 2 slides
Kineto.removeSlide('#carousel', -2, 2);
.replaceSlides()
Replace existing slides with new ones. (Please note that the method name is plural.) If replacing slides are not specified, empty the carousel.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
positionnumber
— Optional. The index of the slide to remove.@param
deleteCountnumber
— Optional. The number of slides to remove fromposition
.
// Remove all slides
Kineto.replaceSlides('#carousel');
// Remove all slides and insert a new slide
Kineto.replaceSlides('#carousel', 'new');
// Remove all slides and insert 2 new slides
Kineto.replaceSlides('#carousel', ['new1', 'new2']);
.play()
Move to the next slide periodically. (The time interval between
each tick can be configured through
streamEvery
option.)
After hitting the last slide, return to the first one. (You can
choose not to do so by setting streamRewind
option
to false
.
.pause()
Stop moving to the next slide.
.on()
Bind a listener to Kineto's internal event. Read Events for more details.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
typestring
— The name of the event to listen to. -
@param
listenerfunction
— The event handler to bind.
// Do something when `#carousel` completes a movement.
Kineto.on('#carousel', 'changed', function(currentIndex, previousIndex) {
// ...
});
.off()
Unbind a listener that has been bound through
.on()
method above. Read
Events for more details. The type and the
listener should be identical to those used in
binding process.
-
@param
containerstring | HTMLElement
— The container element or its selector. -
@param
typestring
— The name of the event to remove. -
@param
listenerfunction
— The event handler to unbind.
// Handler for gallery change
function handleGalleryChange(currentIndex, previousIndex) { }
// Bind the handler
Kineto.on('#carousel', 'changed', handleGalleryChange);
// Unbind the handler
Kineto.off('#carousel', 'changed', handleGalleryChange);
Events
The event listeners you registered using
Kineto.on()
method, are invoked every time Kineto
emits relevant event.
// Register an event listener
Kineto.on(container, type, listener);
// Unregister an event listener
Kineto.off(container, type, listener);
Some of them receives extra information about the event occured; please find the details below.
init
Event fired on completion of the initialization process. The handler should be added before the initialization.
Kineto
.on('#carousel', 'init', function() {}) // Bind the listener first
.create('#carousel'); // Then init
destroy
Event fired at the beginning of destruction of the instance. The handler should be added beforehand.
Kineto
.on('#carousel', 'destroy', function() {})
.create('#carousel');
change
-
@param
nextIndexnumber
— The index of slide that we are moving towards. -
@param
currentIndexnumber
— The index of currently active slide before moving.
Event fired before moving to another slide.
Kineto.on('#carousel', 'change', function(nextIndex, currentIndex) {});
changed
-
@param
currentIndexnumber
— The index of currently active slide after moving. -
@param
previousIndexnumber
— The index of previously active slide.
Event fired after moving to another slide.
Kineto.on('#carousel', 'change', function(currentIndex, previousIndex) {});
FAQ
The name "Kineto" comes from the word kinetoscope. We find a carousel's behavior similar to that of a kinetoscope; showing a fraction of the content while having more to discover behind the frame.
The inner container of a "Kineto" instance determining which sequence should be shown is called "scope".
The most common reason of broken layouts comes from a hidden ancestor element. Kineto requires the container element to be visible at the moment of initialization, to be able to measure the size of elements that make up the carousel.
You can solve the issue either by calling
Kineto.reload()
or lazy-init Kineto when the
parent element gets visible.
// Example 1. Force-refresh Kineto on demand
modal.on('open', function() {
Kineto.reload('.carousel-inside-modal');
});
// Example 2. Init Kineto on demand
modal.on('open', function() {
Kineto.create('.carousel-inside-modal');
});