Snap Carousel

A lightweight vanilla JavaScript carousel library built with modern web technologies. Based on custom elements, scroll-snap, and scroll-padding.

Getting Started

Quick setup guide to get you started with Snap Carousel
<!-- Option 1: Using CDN (recommended for production) -->
<script src="https://unpkg.com/snap-carousel.js@latest/dist/snap-carousel.umd.min.js"></script>

<!-- Option 2: Using local file -->
<script src="path/to/snap-carousel.umd.js"></script>

<!-- Use the carousel component (auto-registered) -->
<snap-carousel displayed="1" controls nav>
  <div slot="scroller">
    <div>Slide 1</div>
    <div>Slide 2</div>
    <div>Slide 3</div>
  </div>
</snap-carousel>

<!-- Or create a custom carousel using JavaScript -->
<script>
  // Features are available on the global SnapCarousel object
  const { createCarousel, ControlsFeature, NavFeature } = SnapCarousel;
  const CustomCarousel = createCarousel(ControlsFeature, NavFeature);
  customElements.define('custom-carousel', CustomCarousel);
</script>

Basic Usage

Core features with smooth scrolling and autoplay
<snap-carousel
    displayed="1"
    per-page="1"
    nav
    controls
    gap="16"
    padding="16"
    behavior="smooth"
    loop
    pager
    autoplay="3000"
    use-pause
    responsive='[{"breakpoint": "1025", "settings": {"displayed": "2"}}]'
>
</snap-carousel>

Examples

Real-world examples and use cases

Product Showcase

Responsive product grid with loop
<snap-carousel
  displayed="3"
  per-page="2"
  gap="1rem"
  padding="2rem"
  controls
  nav
  loop
>
...
</snap-carousel>
  • Premium Headphones

    Premium Headphones

    $299.99

  • Wireless Earbuds

    Wireless Earbuds

    $159.99

  • Smart Watch

    Smart Watch

    $399.99

  • Fitness Tracker

    Fitness Tracker

    $199.99

  • Fitness Tracker

    Fitness Tracker

    $199.99

  • Fitness Tracker

    Fitness Tracker

    $199.99

Testimonials

Auto-playing testimonials with pause on hover
<snap-carousel
  displayed="1"
  gap="2rem"
  controls
  nav
  autoplay="5000"
  use-pause
>
...
</snap-carousel>
  • "Amazing product! Exactly what I needed."
    John Doe
    John Doe CEO, TechCorp
  • "The best solution we've found in the market."
    Jane Smith
    Jane Smith Product Manager, DesignCo
  • "Outstanding support and regular updates."
    Mike Johnson
    Mike Johnson Developer, DevTeam

Image Gallery

Full-width gallery with captions
<snap-carousel
  displayed="1"
  nav
>
...
</snap-carousel>

Real Estate Listings

Property showcase with detailed information cards
<snap-carousel
  displayed="2"
  per-page="1"
  gap="2rem"
  controls
  nav
  class="property-listings"
>
...
</snap-carousel>
  • Modern City Apartment

    $850,000

    3 beds 2 baths 1,500 sq ft

    📍 Downtown, City

  • Luxury Beachfront Villa

    $2,500,000

    5 beds 4 baths 3,200 sq ft

    📍 Coastal Area

  • Spacious Family Home

    $675,000

    4 beds 3 baths 2,400 sq ft

    📍 Suburban Area

Product Comparison

Multi-row feature comparison with sticky headers
<snap-carousel
  displayed="3"
  per-page="1"
  gap="2rem"
  controls
  nav
  class="comparison-table"
>
...
</snap-carousel>
  • Basic Plan

    Basic Plan

    $9.99/month

    Cloud Storage 50GB
    Users 1
    Support Email
    Custom Domain
  • Enterprise Plan

    Enterprise Plan

    $49.99/month

    Cloud Storage Unlimited
    Users Unlimited
    Support Priority
    Custom Domain
  • Custom Plan

    Custom Plan

    Contact Us

    Cloud Storage Custom
    Users Custom
    Support Dedicated
    Custom Domain

Film Showcase

Netflix-style movie carousel with hover details
<snap-carousel
    displayed="3"
    per-page="3"
    gap="1rem"
    padding="0 2rem"
    controls
    nav
    class="film-carousel"
>
...
</snap-carousel>
  • The Last Frontier
    12+ ★ 8.5

    The Last Frontier

    2024 2h 15m 4K

    A thrilling space exploration journey to the edges of our solar system reveals unexpected discoveries.

    Sci-Fi Adventure
  • Urban Legends
    15+ ★ 7.9

    Urban Legends

    2024 1h 55m HD

    Modern myths come to life in this psychological thriller that blends reality with urban folklore.

    Thriller Mystery
  • The Grand Heist
    16+ ★ 8.2

    The Grand Heist

    2024 2h 30m 4K

    A masterful team of thieves attempts the most daring museum heist in history.

    Action Crime
  • Echoes of Time
    12+ ★ 8.7

    Echoes of Time

    2024 2h 05m 4K

    A mysterious artifact allows a historian to communicate with people from different time periods.

    Drama Fantasy
  • Wild Hearts
    PG ★ 7.8

    Wild Hearts

    2024 1h 45m HD

    An unlikely friendship forms between a young girl and a wild horse in the American wilderness.

    Family Adventure
  • The Last Frontier
    12+ ★ 8.5

    The Last Frontier

    2024 2h 15m 4K

    A thrilling space exploration journey to the edges of our solar system reveals unexpected discoveries.

    Sci-Fi Adventure
  • Urban Legends
    15+ ★ 7.9

    Urban Legends

    2024 1h 55m HD

    Modern myths come to life in this psychological thriller that blends reality with urban folklore.

    Thriller Mystery
  • The Grand Heist
    16+ ★ 8.2

    The Grand Heist

    2024 2h 30m 4K

    A masterful team of thieves attempts the most daring museum heist in history.

    Action Crime
  • Echoes of Time
    12+ ★ 8.7

    Echoes of Time

    2024 2h 05m 4K

    A mysterious artifact allows a historian to communicate with people from different time periods.

    Drama Fantasy
  • Wild Hearts
    PG ★ 7.8

    Wild Hearts

    2024 1h 45m HD

    An unlikely friendship forms between a young girl and a wild horse in the American wilderness.

    Family Adventure

Custom Navigation & addictionnal options

Showcase of customized navigation styles and additional options
<snap-carousel
    displayed="1"
    controls
    nav
    pager
    scrollbar
    vertical
    stop
    class="custom-nav-carousel"
    style="height: 400px;"
>
  <style>
    .custom-pagination {
      gap: .7rem;
      display: flex;
      position: absolute;
      bottom: 1rem;
      width: 100%;
      justify-content: center;
    }

    .custom-pagination button {
      font-size: 0;
      border: none;
      padding: 20px 0;
      background: transparent;
      cursor: pointer;
    }

    .custom-pagination button::after {
      content: '';
      display: block;
      width: 3rem;
      height: 0.3rem;
      padding: 0;
      border-radius: 0;
      background: var(--border);
      transition: all 0.3s ease;
      font-size: 0px;
      transform: translateY(2px);
    }

    .custom-pagination [aria-current="true"]::after {
      background: var(--primary);
    }

    .custom-pagination button:hover::after {
      background: var(--primary-dark);
      transform: none;
    }

    .custom-nav-carousel::part(next-button) {
      position: absolute;
      right: 1rem;
      top: 50%;
      transform: translateY(-50%);
    }

    .custom-nav-button {
      border-radius: 30px;
      pointer-events: auto;
      background: var(--secondary);
      box-shadow: var(--shadow);
      color: #333;
      padding: 8px;

      position: absolute;
      top: 50%;
      transform: translateY(-50%);
      border: none;
      left: 1rem;
    }

    .custom-nav-button[disabled] {
      opacity: 0.5;
      cursor: not-allowed;
    }

    .custom-nav-button:hover {
      scale: 1.1;
    }

    .custom-nav-button[modifier="2"] {
      transform: translateY(50px);
    }

    .custom-nav-carousel::part(pager) {
      position: absolute;
      top: 1rem;
      right: 1rem;
      background: var(--bg);
      padding: 0.5rem 1rem;
      border-radius: var(--radius-lg);
      box-shadow: var(--shadow);
      margin: 0;
    }

    .custom-nav-carousel::part(current) {
      font-size: 2rem;
      color: var(--text);
    }

    .custom-nav-carousel::part(buttons) {
      margin: 0;
    }
  </style>
  <ul slot="scroller">
    <li style="position: sticky;left: 0;top: 0;">
      <div style="background: var(--primary); color: #FFF; padding: 1rem; border-radius: var(--radius-md);position: absolute;width: 200px;top:2rem;left:2rem;">
        This item is not counted as a slide
      </div>
    </li>
    <li>
      <div class="nav-demo-slide">
        <h3>Custom Navigation Demo</h3>
        <p>Showcasing different navigation styles</p>
      </div>
    </li>
  </ul>

  <div slot="pagination" class="custom-pagination">
    <!-- buttons will be added here automatically -->
  </div>

  <!-- Change the default prev button by a custom one -->
  <button slot="prev-buttons" class="custom-nav-button" direction="prev">
    <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M220-240v-480h80v480h-80Zm520 0L380-480l360-240v480Zm-80-240Zm0 90v-180l-136 90 136 90Z"/></svg>
  </button>

  <!-- Add a completely custom prev button which goes back 2 slides -->
  <button slot="prev-buttons" class="custom-nav-button" direction="prev" modifier="2">Prev (x2)</button>

  <!-- Change the next button icon -->
  <span slot="next-icon">
    <svg xmlns="http://www.w3.org/2000/svg" height="24px" viewBox="0 -960 960 960" width="24px" fill="currentColor"><path d="M660-240v-480h80v480h-80Zm-440 0v-480l360 240-360 240Zm80-240Zm0 90 136-90-136-90v180Z"/></svg>
  </span>

  <!-- Change the separator text -->
  <span slot="sep">
    OF
  </span>

  <!-- Remove the next buttton label -->
  <span slot="next-label"></span>
</snap-carousel>
  • This item is not counted as a slide
OF

Module Structure

Different ways to import and use the carousel features

1. Basic Usage (All Features)

<!-- Using UMD bundle in browser (auto-registers the component) -->
<script src="https://unpkg.com/snap-carousel.js@latest/dist/snap-carousel.umd.js"></script>
<snap-carousel displayed="3" gap="20" controls nav>
  <div slot="scroller">
    <div>Slide 1</div>
    <div>Slide 2</div>
    <div>Slide 3</div>
  </div>
</snap-carousel>

2. ES Modules Usage

// Import from npm package
import { SnapCarousel } from 'snap-carousel.js';

// Register the web component
customElements.define('snap-carousel', SnapCarousel);

3. Custom Build with Selected Features

// Import base and features
import { BaseCarousel, createCarousel } from './base-carousel';
import { NavFeature } from './features/nav';
import { PagerFeature } from './features/pager';

// Create custom carousel with only navigation and pager
const CustomCarousel = createCarousel(NavFeature, PagerFeature);
customElements.define('custom-carousel', CustomCarousel);

// Use in HTML
<custom-carousel displayed="3" nav pager>
  <div slot="scroller">...</div>
</custom-carousel>

4. Individual Features

// Import specific features
import { ControlsFeature } from './features/controls';
import { NavFeature } from './features/nav';
import { PagerFeature } from './features/pager';

// Create carousel with only the features you need
const MinimalCarousel = createCarousel(ControlsFeature);
const FullCarousel = createCarousel(ControlsFeature, NavFeature, PagerFeature);

// Register custom elements
customElements.define('minimal-carousel', MinimalCarousel);
customElements.define('full-carousel', FullCarousel);

5. With Module Bundlers

// vite.config.js
export default defineConfig({
  build: {
    lib: {
      entry: 'src/snap-carousel.js',
      formats: ['es', 'umd'],
      fileName: (format, entryName) => {
        const formatSuffix = format === 'es' ? 'esm' : format;
        return `${entryName}.${formatSuffix}.js`;
      },
      name: 'SnapCarousel'
    }
  }
});

// main.js
import { BaseCarousel, createCarousel } from './base-carousel';
import { ControlsFeature } from './features/controls';

// Tree-shaking will remove unused features
const MyCarousel = createCarousel(ControlsFeature);
customElements.define('my-carousel', MyCarousel);

6. Available Imports

// Base carousel and composition
import { BaseCarousel, createCarousel } from './base-carousel';

// Individual features
import { ControlsFeature } from './features/controls';
import { NavFeature } from './features/nav';
import { PagerFeature } from './features/pager';

// Pre-configured variants
import {
  SnapCarousel,          // All features
  SnapCarouselNav,       // Navigation only
  SnapCarouselPager,     // Pager only
  SnapCarouselControls,  // Controls only
  SnapCarouselNavControls,
  SnapCarouselNavPager,
  SnapCarouselPagerControls
} from './snap-carousel';
  • Modular Design

    Import only what you need

  • Tree Shaking

    Optimize bundle size

  • Custom Features

    Mix and match carousel features

Options Reference

Complete list of available carousel options and their descriptions

displayed

Type: number
Default: 1

Number of items visible in the viewport at once.

per-page

Type: number
Default: 1

Number of items to scroll per navigation action.

gap

Type: string
Default: "0"

Space between carousel items (CSS units, e.g., "1rem", "16px").

padding

Type: string
Default: "0"

Inline Padding around the carousel viewport (CSS units, you can specify both left and right padding e.g., "0px 4rem").

controls

Type: boolean
Default: false

Show previous/next navigation buttons.

nav

Type: boolean
Default: false

Show navigation dots for direct slide access.

pager

Type: boolean
Default: false

Show current/total slides counter (e.g., "1 / 5").

loop

Type: boolean
Default: false

Enable infinite looping of carousel items.

autoplay

Type: number
Default: 0

Autoplay interval in milliseconds (0 to disable).

use-pause

Type: boolean
Default: false

Pause autoplay on hover.

behavior

Type: string
Default: "smooth"

Scroll behavior ("smooth" or "auto").

stop

Type: boolean
Default: false

Force stopping at each step. (scroll-snap-stop: always)

vertical

Type: boolean
Default: false

Enable vertical scrolling mode instead of horizontal.

responsive

Type: object
Default: null

Breakpoint-specific settings (e.g., responsive='[{"breakpoint": "1024", "settings": {"displayed": "2"}}]').

scrollbar

Type: boolean
Default: false

Show scrollbar.

sync

Type: string
Default: null

CSS selector for the carousel to sync with.