Demo 01

Responsive Multi-Slide

Three slides on desktop, two on tablet, one on phone. Resize the browser to watch the breakpoints trigger.

new Slickless("#multi-carousel", {
  slidesToShow: 3,
  slidesToScroll: 1,
  dots: true,
  infinite: true,
  responsive: [
    { breakpoint: 960, settings: { slidesToShow: 2 } },
    { breakpoint: 600, settings: { slidesToShow: 1 } },
  ],
});
Demo 02

Fade Transition

Cross-fade between full-width slides with autoplay. Pauses on hover and focus for reading comfort.

new Slickless("#fade-carousel", {
  fade: true,
  autoplay: true,
  autoplaySpeed: 3500,
  speed: 700,
  dots: true,
  arrows: false,
  infinite: true,
});
Demo 03

Vertical Stack

Stacked navigation with vertical drag. Three items visible — swipe up and down.

new Slickless("#vertical-carousel", {
  vertical: true,
  slidesToShow: 3,
  slidesToScroll: 1,
  arrows: true,
  infinite: true,
  speed: 400,
});
Demo 04

Center Mode

Focused slide sits in the center while siblings peek from the sides. Drag the slider to adjust centerPadding.

60px
new Slickless("#center-carousel", {
  centerMode: true,
  centerPadding: "60px",
  slidesToShow: 3,
  focusOnSelect: true,
  infinite: true,
  speed: 400,
  arrows: true,
  responsive: [
    { breakpoint: 720, settings: { slidesToShow: 1, centerPadding: "30px" } },
  ],
});
Demo 05

Linked Carousels

A main stage synced to a thumbnail strip. Click any thumbnail in the nav to jump the main stage.

// Initialise the nav strip first so the main stage can subscribe to it.
new Slickless("#nav-strip", {
  slidesToShow: 5,
  slidesToScroll: 1,
  arrows: false,
  focusOnSelect: true,
  infinite: false,
  draggable: false,
  speed: 300,
});

new Slickless("#main-stage", {
  slidesToShow: 1,
  arrows: true,
  fade: true,
  asNavFor: "#nav-strip",
  infinite: true,
  speed: 600,
});
Demo 06

Custom Paging

Replace the default dot bullets with fraction indicators — or any custom element you return.

new Slickless("#custom-paging-carousel", {
  slidesToShow: 1,
  arrows: false,
  dots: true,
  speed: 500,
  infinite: true,
  customPaging: (i, total) => {
    const btn = document.createElement("button");
    btn.type = "button";
    btn.className = "frac-btn";
    btn.setAttribute("aria-label", `Go to slide ${i + 1}`);
    btn.textContent = `${String(i + 1).padStart(2, "0")} / ${String(total).padStart(2, "0")}`;
    return btn;
  },
});
Demo 07

Adaptive Height

The viewport resizes to match each slide's natural height. Toggle the switch to lock it back down.

adaptiveHeight on
const carousel = new Slickless("#adaptive-carousel", {
  adaptiveHeight: true,
  dots: true,
  infinite: true,
  speed: 450,
});

// Toggle the option at runtime — setOptions rebuilds the carousel.
toggle.addEventListener("change", () =>
  carousel.setOptions({ adaptiveHeight: toggle.checked }));
Demo 08

Variable Width

Each slide keeps its own natural width — perfect for tag rails, chip lists, or mixed-aspect cards.

variableWidth on
const carousel = new Slickless("#varwidth-carousel", {
  variableWidth: true,
  slidesToScroll: 1,
  infinite: true,
  speed: 350,
});

// Toggle the option at runtime — setOptions rebuilds the carousel.
toggle.addEventListener("change", () =>
  carousel.setOptions({ variableWidth: toggle.checked }));
Demo 09

Lazy Image Loading

Images load only when approaching the viewport. Switch modes to see the difference — reset to reload from scratch.

0 / 6 images loaded Navigate to load the next one.
<div id="lazy-carousel">
  <img data-lazy="…/mountain.jpg" alt="" />
  <img data-lazy="…/forest.jpg" alt="" />
  … more slides
</div>

const lazy = new Slickless("#lazy-carousel", {
  lazyLoad: "ondemand",  // or "progressive" / false
  dots: true,
  infinite: false,
});

// fires for every image as it resolves
lazy.on("lazyLoaded", ({ image, src }) =>
  console.log("loaded:", src));
Demo 10

Event System

Subscribe to lifecycle events. Swipe, click an arrow, or hit an edge — the log fills in real time.

Event Log
  1. Ready — try the arrows or a swipe.
const carousel = new Slickless("#events-carousel", {
  dots: true,
  infinite: false,
  speed: 400,
});

carousel.on("init", () => log("init"));

carousel.on("beforeChange", ({ currentSlide, nextSlide }) =>
  log(`beforeChange: ${currentSlide} → ${nextSlide}`));

carousel.on("afterChange", ({ currentSlide }) =>
  log(`afterChange: now on ${currentSlide}`));

carousel.on("swipe", ({ direction }) =>
  log(`swipe: ${direction}`));

carousel.on("edge", ({ direction }) =>
  log(`edge hit: ${direction}`));

// Also available as DOM events:
// carousel.root.addEventListener("slickless:afterChange", e => ...);