Documentation
Markup
Every direct child of the container is a slide. No wrapper elements needed.
<div class="slider">
<div>Slide 1</div>
<div>Slide 2</div>
<div>Slide 3</div>
</div>Initialising
import Mozert from '@mozert-studio/mozert-slider';
const slider = new Mozert('.slider', { dots: true, autoplay: true });<div class="slider" data-mozert='{"slidesToShow":3,"spaceBetween":16}'>…</div>
<!-- elements with data-mozert are initialised automatically.
Set window.MozertAutoInit = false before loading to disable. -->$('.slider').mozert({ dots: true });
$('.slider').mozert('next');
$('.slider').on('afterChange', function (e, slider, current) {});Options
Defaults come from Mozert.defaults. Change them globally by assigning to it.
| Option | Default | Description |
|---|---|---|
accessibility | true | Adds ARIA roles/labels and keyboard support. |
adaptiveHeight | false | Animate the list height to the active slide (single-slide views). |
appendArrows | null | Element or selector to place both arrows in (for example a control bar under the slider). Default: inside the slider. |
appendDots | null | Element or selector to place the dots in. Default: inside the slider, under the slides. |
arrows | true | Show previous/next arrows. |
asNavFor | null | Selector of another slider to keep in sync (thumbnails, controllers). |
autoplay | false | Start automatically. |
autoplayReverse | false | Autoplay moves backwards. |
autoplaySpeed | 3000 | Delay between slides in ms. |
bleed | false | true, "left" or "right". Slides overflow the container towards the viewport edge; the first and last slide still align with the container. Forces infinite: false and sets overflow-x: clip on body so the page gets no horizontal scrollbar. |
cardsEffect | {…} | perSlideOffset, perSlideRotate, rotate, visible. |
centerMode | false | Centre the active slide; neighbours peek. |
centerPadding | "50px" | Width of the peek on each side in centerMode: "50px" or "10%". Change it per screen size with responsive. |
coverflowEffect | {…} | rotate, depth, stretch, scale, modifier, lift (raises background cards), fade (dims them). |
creativeEffect | {…} | prev / next with translate, rotate, opacity, scale; limitProgress. |
cssEase | "ease" | CSS easing for transitions. |
cubeEffect | {…} | perspective. |
customPaging | null | Function (slider, i) returning markup for dot i. |
disableOnInteraction | false | Stop autoplay for good after the user clicks, taps or drags. |
dots | false | Show dots. |
dotsClass | "mozert-dots" | Class of the dots list. |
dragThreshold | 6 | Pixels to move before a drag starts. |
draggable | true | Mouse dragging (touch is controlled by swipe). |
easing | "linear" | Easing used when useCSS is false. |
edgeFriction | 0.15 | Resistance when dragging past the first/last slide (non-infinite). |
edgePadding | 0 | Space before the first and after the last slide (px or %). |
effect | "slide" | slide, fade, coverflow, cube, flip, cards, creative or expand. |
expandEffect | {…} | extra: how much wider the active card gets, as a multiple of a slide width (default 1.4). The card inside each slide is resized, so give slides a single child element. |
fade | false | Shortcut for effect: "fade". |
flipEffect | {…} | perspective, limitRotation. |
focusOnSelect | false | Clicking a slide makes it active. |
freeMode | false | Drag with momentum and no snapping. Accepts an options object. |
fullscreen | false | Add a fullscreen toggle button. |
globalKeyboard | false | Arrow keys control the slider while it is in the viewport. |
hashNavigation | false | true or { watchState, replaceState, prefix }. Slides use data-hash. |
infinite | true | Loop forever using clones. |
initialSlide | 0 | First slide index. |
labels | null | Object overriding built-in ARIA strings (translations). |
lazyLoad | "ondemand" | ondemand or progressive. |
lightbox | false | Click a slide to open it full screen. true or { zoom, loop, maxZoom }. |
magnifier | false | Hover zoom for product galleries. true or { zoom: 2.2, button: true, active: false }. A button in the top right corner turns it on and off; data-zoom on an image loads a sharper file. |
marquee | false | { speed, pauseOnHover, direction }. Continuous ticker. |
mobileFirst | false | Breakpoints are min-width instead of max-width. |
mousewheel | false | true or { sensitivity, forceToAxis, releaseOnEdges, thresholdTime }. |
nextArrow | null | Your own markup (an HTML string) or an element for the next arrow. It gets the class mozert-next and works as the next button. |
on | null | Event handlers object, e.g. { afterChange(s, i) {} }. |
pagination | false | { el, type, clickable, renderBullet, ... }. Types: bullets, dynamic, fraction, progressbar, custom. |
parallax | false | Enable data-parallax-* attributes. |
pauseOnDotsHover | false | Pause autoplay when hovering the dots. |
pauseOnFocus | true | Pause autoplay on keyboard focus. |
pauseOnHover | true | Pause autoplay on hover. |
prevArrow | null | Your own markup (an HTML string) or an element for the previous arrow. It gets the class mozert-prev and works as the previous button. |
respectReducedMotion | true | Disable autoplay/animation for prefers-reduced-motion users. |
respondTo | "window" | window, slider or min width used for breakpoints. |
responsive | null | Array of { breakpoint, settings }. settings: "destroy" turns the slider off at that breakpoint. |
rows | 1 | Grid rows. |
rtl | false | Right-to-left layout for Arabic, Hebrew, Urdu and other RTL pages. Slides start from the right, swipe, arrows and keyboard arrows are reversed, and dir="rtl" is set on the slider. |
scrollDriven | false | Page scroll moves the slides while the slider sticks to the top. true or { fill, speed, top, offset, bottom, step }. Horizontal, non-looping sliders only. |
scrollbar | false | true or { el, draggable, hide }. |
slide | "" | Selector of the slide elements inside the container. |
slideWidth | 0 | Fixed slide width in px; slides per view is computed. |
slidesPerRow | 1 | Columns per page when rows > 1. |
slidesToScroll | 1 | Slides per move. |
slidesToShow | 1 | Slides visible (fractional allowed). |
spaceBetween | 0 | Gap between slides in px. |
speed | 300 | Transition time in ms. |
stopOnLastSlide | false | Stop autoplay after the last slide (non-infinite). |
swipe | true | Touch swiping. |
swipeToSlide | false | Land on the slide nearest the release point. |
thumbs | false | true builds a thumbnail strip below the slider; a selector or element uses your own strip; { el, count, options } for more control. Keeps both sliders in sync. |
touchMove | true | Slides follow the finger. |
touchRatio | 1 | Drag distance multiplier. |
touchThreshold | 5 | Fraction of the width needed to change slide (width / value). |
useCSS | true | CSS transitions (false = JS animation). |
useTransform | true | Use transform instead of left/top. |
variableWidth | false | Slides keep their own width. |
vertical | false | Vertical slider. |
verticalSwiping | false | Vertical swipe gestures. |
videoAutoplay | false | Play the active slide's <video>. { wait } holds autoplay until it ends. |
virtual | false | { slides, renderSlide, addSlidesBefore, addSlidesAfter, cache }. |
waitForAnimate | true | Ignore input while animating. |
zIndex | 1000 | Base z-index for stacked effects. |
zoom | false | true or { max, min, toggle, step }. |
Responsive
Breakpoints are max-width by default; add mobileFirst: true for min-width breakpoints. Only the matching breakpoint's settings override the base.
new Mozert('.slider', {
slidesToShow: 4,
responsive: [
{ breakpoint: 1024, settings: { slidesToShow: 3 } },
{ breakpoint: 600, settings: { slidesToShow: 1.5, spaceBetween: 8 } },
{ breakpoint: 400, settings: 'destroy' } // destroy below 400px
]
});Effects
Choose with effect. Each effect reads its own options object. They respond to dragging, so the slide follows your finger.
new Mozert('.slider', {
effect: 'coverflow',
slidesToShow: 3,
coverflowEffect: { rotate: 40, depth: 140, stretch: 0, modifier: 1, scale: 0.8, lift: 60, fade: 0.2 } // lift raises background cards, fade dims them
});
// Expanding cards: the active card opens wide, the others stay narrow
new Mozert('.slider', {
effect: 'expand',
slidesToShow: 4.4,
expandEffect: { extra: 1.4 } // how much wider the active card gets (1.4 = 140% of a slide)
});
new Mozert('.slider', {
effect: 'creative',
creativeEffect: {
prev: { translate: ['-120%', 0, -300], rotate: [0, 0, -6], opacity: 0 },
next: { translate: ['100%', 0, 0] }
}
});slidesToShow is forced to 1). Coverflow and expand centre the active slide and support several visible slides.Pagination
new Mozert('.slider', {
pagination: {
el: '#my-pagination', // optional, otherwise created inside the slider
type: 'bullets', // 'bullets' | 'dynamic' | 'fraction' | 'progressbar' | 'custom'
clickable: true,
renderBullet: (i, cls) => '<button class="' + cls + '">' + (i + 1) + '</button>',
renderCustom: (slider, current, total) => current + ' of ' + total // for type: 'custom'
},
scrollbar: { draggable: true, hide: false }
});dots (simple dot list) and pagination (typed pagination) are independent; use either.
Free mode, mousewheel, keyboard
new Mozert('.slider', {
freeMode: { momentum: true, momentumRatio: 1, sticky: false },
mousewheel: { sensitivity: 1, releaseOnEdges: true },
globalKeyboard: true,
slidesToShow: 3.2, infinite: false
});Parallax
<div class="slider" data-mozert='{"parallax":true,"speed":700}'>
<div>
<img src="a.jpg" data-parallax-x="-20%" alt="">
<h2 data-parallax-x="-60%" data-parallax-opacity="0">Title</h2>
</div>
</div>
<!-- Values are the offset when the slide is one position away. Add data-parallax-bg on an element inside the slider to move a background layer. -->Zoom
Double-click or double-tap an img/canvas/video (or an element with class mozert-zoom-target) in the active slide. Pinch on touch screens, ctrl+wheel on desktop. While zoomed, dragging pans the image.
const s = new Mozert('.gallery', { zoom: { max: 3 } });
s.zoom.toggle(); s.zoom.in(); s.zoom.out(); s.zoom.reset();
s.on('zoomChange', (slider, scale) => {});Virtual slides
const slider = new Mozert('#big', {
virtual: {
slides: myArrayOf10000Items,
renderSlide: (item, i) => '<div class="card">' + item.title + '</div>', // optional
addSlidesBefore: 2, addSlidesAfter: 3,
cache: false // false = unload slides that leave the window
},
slidesToShow: 3
});
slider.virtual.appendSlide(item); slider.virtual.prependSlide(item); slider.virtual.removeSlide(0); slider.virtual.update();Start with an empty container element; Mozert creates lightweight slide shells and fills only those near the viewport. Virtual mode disables infinite.
Lazy loading
<img data-lazy="photo.jpg" data-lazy-srcset="photo-2x.jpg 2x" alt="">
<div data-lazy-bg="hero.jpg"></div>
<!-- lazyLoad: 'ondemand' (default) loads when a slide is about to show; 'progressive' loads the rest after the first paint. -->Events: lazyLoaded and lazyLoadError.
Arrows and dots
// Your own arrow markup
new Mozert('.slider', {
prevArrow: '<button type="button" class="my-arrow">← Prev</button>',
nextArrow: '<button type="button" class="my-arrow">Next →</button>'
});
// Put the arrows and the dots in a control bar anywhere on the page
// <div class="bar"><div id="arrows"></div><div id="dots"></div></div>
new Mozert('.slider', {
appendArrows: '#arrows', // selector or element
appendDots: '#dots',
dots: true
});prevArrow and nextArrow take an HTML string or an element, so the arrows can look and read however you want. Mozert adds the classes mozert-prev / mozert-next and wires the clicks, the disabled state at the ends and the aria-label. appendArrows and appendDots move the arrows and the dots out of the slider into any element. The default round arrows are positioned over the slider, so when you append them elsewhere give them your own style (for example position: static). The dots keep working with customPaging, dotsClass and dots: 'dynamic' style pagination. See the live example on the Examples page.
Center padding
new Mozert('.slider', {
centerMode: true,
centerPadding: '140px', // peek width on each side: px or %
slidesToShow: 1,
responsive: [{ breakpoint: 640, settings: { centerPadding: '36px' } }]
});In centerMode the active slide stays in the middle and centerPadding sets how much of the neighbours you see on each side. Use pixels or a percentage, and shrink it on phones with responsive. It works with infinite, arrows, dots and the effects that centre the active slide.
Right to left (rtl)
new Mozert('.slider', {
rtl: true,
slidesToShow: 2.2,
dots: true
});rtl: true is for right-to-left pages. The slides start from the right, swiping, the previous/next arrows and the keyboard arrow keys follow the reading direction, and the slider gets dir="rtl" so your text and layout flip with it. It works with vertical off, with infinite, centerMode, thumbs and every pagination type. See the live example on the Examples page.
Thumbnails
// One option: a strip is created below the slider
new Mozert('#gallery', { thumbs: true });
// Your own strip (left empty it is filled for you; filled by you it is used as is)
new Mozert('#gallery', { thumbs: '#nav' });
new Mozert('#gallery', { thumbs: { el: '#nav', count: 4, options: { spaceBetween: 6 } } });
// Vertical gallery: main picture on the left, thumbnails stacked on the right
new Mozert('#gallery', { thumbs: { position: 'right', count: 4 } });
// position: 'left' | 'right' | 'top' | 'bottom' (default)Thumbnails come from data-thumb on the slide, then the first <img>, then the slide's background. Clicking a thumbnail opens that slide, and changing slides highlights the matching thumbnail, even when the strip has nothing to scroll.
Lightbox
new Mozert('#gallery', { lightbox: true });
new Mozert('#gallery', { lightbox: { zoom: true, loop: true, maxZoom: 2.5 } });
<!-- Big image: data-full on the slide or img, or a link to the file. Caption: data-caption. -->
<div data-caption="Sunrise"><a href="photos/sunrise-large.jpg"><img src="photos/sunrise.jpg" alt="Sunrise"></a></div>
slider.lightbox.open(2); slider.lightbox.close(); slider.lightbox.isOpen;Arrow keys, swipe, Esc, click the picture to zoom, focus is kept inside the dialog and returns to where you were. When you close it the slider shows the last picture you viewed. Events: lightboxOpen, lightboxChange, lightboxClose. Ordinary links inside slides still work.
Magnifier
// Product gallery: thumbnails on the left, hover zoom on the picture
new Mozert('#product', {
thumbs: { position: 'left', count: 4 },
magnifier: true // or { zoom: 2.4, button: true, active: false }
});
<img src="shoe-800.jpg" data-zoom="shoe-2400.jpg" alt="Shoe"> <!-- optional sharper file -->
slider.magnifier.enable(); slider.magnifier.disable(); slider.magnifier.toggle(); slider.magnifier.isOn();A small magnifier button sits in the top right corner of the picture. When it is on, moving the mouse over a slide enlarges it around the pointer, like a product page in a shop. It is for mouse users only; touch screens keep normal swiping, and dragging the slider turns the zoom off while you hold the button. Set button: false to hide the button and control it with the API instead. Event: magnifier.
Scroll-driven
new Mozert('#story', {
scrollDriven: {
fill: true, // the pinned slider takes the whole screen height: no empty space above or below
offset: 76, // px kept free at the top for a sticky header
bottom: 24, // px kept free at the bottom
// top: 'center' // without fill: pin in the middle of the screen (or a number of px from the top)
speed: 1.6 // px the slides travel per px of scroll: higher = shorter section, less empty space
},
infinite: false, arrows: false, dots: false, draggable: false
});The slider is wrapped in a tall section and sticks while you scroll through it. The section is only as tall as the slides need to travel divided by speed; use step (px of scrolling per slide) if you want a fixed distance instead. To avoid empty space above and below, make the slider as tall as the screen under your header, for example .story .slide { height: calc(100svh - 96px) } with top: 76 (the header height plus a small gap). Needs a horizontal, non-looping slider, and no ancestor with overflow: hidden (that breaks position: sticky).
Synced sliders
new Mozert('#main', { arrows: false, asNavFor: '#thumbs' });
new Mozert('#thumbs', { slidesToShow: 5, asNavFor: '#main', focusOnSelect: true });Accessibility
- Container gets
role="region"andaria-roledescription="carousel"; slides getrole="group"with "n of total" labels; clones are hidden from assistive tech. - Left/right (up/down when vertical) keys work when the slider has focus;
globalKeyboardextends this to the whole page. - Autoplay pauses on hover and focus, and the live region switches to
politewhen autoplay is off or paused. - Users with
prefers-reduced-motion: reduceget no autoplay and instant transitions (disable withrespectReducedMotion: false). - Translate all strings with the
labelsoption.
Theming
.my-slider {
--mozert-accent: #3633f5;
--mozert-arrow-bg: #fff;
--mozert-arrow-fg: #111;
--mozert-arrow-size: 44px;
--mozert-dot-color: #bbb;
--mozert-dot-active: #3633f5;
--mozert-dot-size: 10px;
}mozert-theme.css is optional: it only styles arrows and dots. Core layout lives in mozert.css.