UNPKG

preline

Version:

Preline UI is an open-source set of prebuilt UI components based on the utility-first Tailwind CSS framework.

391 lines (295 loc) 15.2 kB
# Carousel Build carousels and sliders with Carousel JavaScript plugin. [![npm](https://img.shields.io/badge/npm-v4.2.0-blue)](https://www.npmjs.com/package/@preline/carousel) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Demo](https://img.shields.io/badge/demo-online-brightgreen)](https://preline.co/plugins/carousel.html) ## Contents - [Overview](#overview) - [Installation](#installation) - [Basic usage](#basic-usage) - [Configuration Options](#configuration-options) - [JavaScript API](#javascript-api) - [Events](#events) - [Common Patterns](#common-patterns) - [License](#license) ## Overview The Carousel component provides a flexible, feature-rich slider for displaying multiple items in a scrollable container. It supports autoplay, infinite loop, drag gestures, responsive breakpoints, and multiple display modes. **Key Features:** - Multiple slides in a scrollable container - Autoplay and infinite loop support - Drag/swipe gestures for navigation - Responsive breakpoints for different screen sizes - Multiple display modes (default, snap, bounded) - Programmatic control via JavaScript API - Keyboard navigation support - Customizable pagination dots ## Installation To get started, install Carousel plugin via npm, else you can skip this step if you are already using Preline UI as a package. ```bash npm i @preline/carousel ``` ### CSS Use [`@source`](https://tailwindcss.com/docs/functions-and-directives#source-directive) to register the plugin's JavaScript path for Tailwind CSS scanning, then [`@import`](https://tailwindcss.com/docs/functions-and-directives#import-directive) the plugin's CSS files into your Tailwind CSS file. ```css @import "tailwindcss"; /* @preline/carousel */ @source "../node_modules/@preline/carousel/*.js"; @import "./node_modules/@preline/carousel/variants.css"; @import "./node_modules/@preline/carousel/theme.css"; ``` ### JavaScript Include the JavaScript that powers the interactive elements near the end of your `</body>` tag: ```html <script src="./node_modules/@preline/carousel/index.js"></script> ``` ### Manual Initialization Use the `non-auto` entry if you need manual initialization. In this mode, automatic initialization on page load is not included, so the component should be initialized explicitly. ```html <script type="module"> import HSCarousel from "@preline/carousel/non-auto.mjs"; new HSCarousel(document.querySelector("#carousel")); </script> ``` ### Via Bundler When using a bundler (Vite, webpack, etc.), import the plugin directly as an ES module. `@preline/carousel` is the auto-init entry: it scans the DOM and initializes matching elements automatically. ```js import "@preline/carousel"; ``` `@preline/carousel/non-auto` is the manual entry: use it when you want explicit control over when initialization happens, either via `autoInit()` or by creating a specific instance yourself. ```js import HSCarousel from "@preline/carousel/non-auto"; HSCarousel.autoInit(); // Or initialize a specific element manually const el = document.querySelector("#carousel"); if (el) new HSCarousel(el); ``` ### TypeScript This package ships with TypeScript type definitions. No additional `@types/` package is needed. ## Basic usage The following example demonstrates the minimal HTML structure required for a carousel component. This is a base template without custom styling - you can apply your own CSS classes and styles as needed. The carousel displays three slides with previous/next navigation buttons. ```html <div data-hs-carousel='{ "loadingClasses": "opacity-0" }' class="relative"> <div class="hs-carousel relative overflow-hidden w-full min-h-64"> <div class="hs-carousel-body absolute top-0 bottom-0 start-0 flex flex-nowrap transition-transform duration-700 opacity-0"> <div class="hs-carousel-slide"> 1 </div> <div class="hs-carousel-slide"> 2 </div> <div class="hs-carousel-slide"> 3 </div> </div> </div> <button type="button" class="hs-carousel-prev"> <span aria-hidden="true">«</span> <span class="sr-only">Previous</span> </button> <button type="button" class="hs-carousel-next"> <span class="sr-only">Next</span> <span aria-hidden="true">»</span> </button> </div> ``` **Structure Requirements:** - `data-hs-carousel`: Required on the container element, contains configuration options - `hs-carousel`: Required wrapper for slides collection, must contain `overflow-hidden` class - `hs-carousel-body`: Required slides container - `hs-carousel-slide`: Required for each slide element - `hs-carousel-prev`: Optional previous slide button - `hs-carousel-next`: Optional next slide button - `hs-carousel-pagination`: Optional pagination container **Initial State:** - Carousel body typically starts with `opacity-0` which is removed after loading - First slide is active by default (index 0) ## Configuration Options ### Data Options Data options are specified in the `data-hs-carousel` attribute as a JSON object. | Option | Type | Default | Description | | --- | --- | --- | --- | | `currentIndex` | number | `0` | Specifies the index of the current slide initially (from 0 to slides quantity). | | `loadingClasses` | string | `"opacity-0"` | Specifies which classes should be removed after the carousel is loaded. CSS classes should be separated with space. | | `dotsItemClasses` | string | - | Specifies which classes will be added to the point elements (which are generated automatically). CSS classes should be separated with space. | | `isAutoHeight` | boolean | `false` | Sets the height of the carousel to the height of the current slide. | | `isAutoPlay` | boolean | `false` | Enables autoplay. Slides advance automatically at the interval specified by `speed`. | | `isInfiniteLoop` | boolean | `true` | Enables infinite loop. When reaching the last slide, it wraps to the first slide. | | `isCentered` | boolean | `false` | Enables centered mode. This mode adds space on the sides to center the slides. | | `isSnap` | boolean | `false` | Enables a mode in which you can scroll the contents of the slider using the scroll along the x-axis, while the active slider is centered relative to the slider. | | `isScrollBlocked` | boolean | `false` | Prevents the user from scrolling the slider. Useful when you need to prevent scrolling while the carousel is active. | | `isDraggable` | boolean | `false` | Adds the ability to change slides using dragging. Requires adding `hs-carousel:dragging:transition-none` class to the `hs-carousel-body`. Not working with `isSnap: true` option. | | `isRTL` | boolean | `false` | Turns on RTL (right-to-left) mode. | | `hasSnapSpacers` | boolean | `true` | Adds additional elements to create a constant centering effect. | | `slidesQty` | object \| number | `1` | Allows to set the number of slides to display at a certain screen resolution if passed as an object (e.g., `{"xs": 1, "md": 2, "lg": 3}`). If passed as a number, the specified number of slides will be displayed for all screen resolutions. | | `slideBy` | object \| number | `1` | Specifies how many slides to move when navigating through the carousel. Can be a number for all screen sizes or an object with breakpoint-specific values. | | `speed` | number | `4000` | Autoplay animation speed in milliseconds. Available if `isAutoplay: true`. | | `updateDelay` | number | `0` | Allows you to delay the update function when resizing a window. Suitable for a slider with images, for more accurate calculation of the size of the images. | | `mode` | `"default"` \| `"snap"` \| `"bounded"` | `"default"` | Defines the carousel's behavior mode. `default` for standard sliding, `snap` for scroll-based navigation with snap points, and `bounded` for a fixed-width container with responsive slides. | | `boundedOptions` | object | `null` | Configuration options for the bounded mode carousel. Includes `maxWidth` to set the maximum width of the carousel container, `slidesGap` to define spacing between slides, and `spacersWidth` to control the width of side spacers. When `spacersWidth` is set to `"auto"`, it automatically calculates equal spacing on both sides. | **Example:** ```html <div data-hs-carousel='{ "isAutoPlay": true, "speed": 3000, "slidesQty": {"xs": 1, "md": 2, "lg": 3}, "isInfiniteLoop": true }'> <!-- Carousel content --> </div> ``` ### Required CSS Classes These classes define the structure and must be present for the carousel to function. | Class | Required On | Purpose | | --- | --- | --- | | `hs-carousel` | Wrapper container | A wrapper for a collection of slides. Must contain the `overflow-hidden` class for correct functionality. | | `hs-carousel-body` | Slides container | Container for all slide elements. | | `hs-carousel-slide` | Each slide element | Identifies an individual slide. | ### Optional CSS Classes | Class | Required On | Purpose | | --- | --- | --- | | `hs-carousel-prev` | Previous button | Previous slide navigation button. | | `hs-carousel-next` | Next button | Next slide navigation button. | | `hs-carousel-pagination` | Pagination container | Pagination container. If it doesn't contain nested elements, dots are generated automatically. If it contains elements with `hs-carousel-pagination-item` class, they will act as dots. | ### Tailwind Modifiers | Name | Description | | --- | --- | | `hs-carousel-active:*` | A modifier that allows you to set Tailwind classes when the active slide was shown. | | `hs-carousel-disabled:*` | A modifier that allows you to set Tailwind classes for arrow buttons when they are `disabled`. | | `hs-carousel:dragging:*` | A modifier that allows you to set Tailwind classes for `hs-carousel-body` when dragging. | ## JavaScript API The `HSCarousel` object is available in the global `window` object after the plugin is loaded. ### Instance Methods These methods are called on a carousel instance. | Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | `goToPrev()` | None | `void` | Navigates to the previous slide. | | `goToNext()` | None | `void` | Navigates to the next slide. | | `goTo(index)` | `index`: `number` | `void` | Navigates to the slide at the specified index. Index starts from 0. | | `recalculateWidth()` | None | `void` | Recalculates the width of the carousel. Useful after dynamically adding or removing slides, or when window is resized. | | `destroy()` | None | `void` | Destroys the carousel instance, removes all generated markup, classes, and event listeners. Use when removing carousel from DOM. | ### Static Methods These methods are called directly on the `HSCarousel` class. | Method | Parameters | Return Type | Description | | --- | --- | --- | --- | | `HSCarousel.getInstance(target, isInstance)` | `target`: `HTMLElement \| string` (CSS selector)<br>`isInstance`: `boolean` (optional) | `HSCarousel \| { id: string \| number, element: HSCarousel } \| null` | Returns the carousel instance associated with the target. If `isInstance` is `true`, returns collection item object `{ id, element }` where `element` is the `HSCarousel` instance. If `isInstance` is `false` or omitted, returns the `HSCarousel` instance directly. Returns `null` if carousel instance is not found. | ### Usage Examples **Example 1: Using instance methods (public API)** ```javascript // Create a new carousel instance const carousel = new HSCarousel(document.querySelector('#hs-carousel')); const goToSecondBtn = document.querySelector('#hs-go-to-second-btn'); // Navigate to slide by index goToSecondBtn.addEventListener('click', () => { carousel.goTo(1); // Go to second slide (index 1) }); ``` **Example 2: Getting instance and using methods (recommended pattern)** ```javascript // Get the carousel instance const instance = HSCarousel.getInstance('#hs-carousel', true); if (instance) { const { element } = instance; // element is the HSCarousel instance const goToSecondBtn = document.querySelector('#hs-go-to-second-btn'); const prevBtn = document.querySelector('#hs-prev-btn'); const nextBtn = document.querySelector('#hs-next-btn'); // Navigate to specific slide goToSecondBtn.addEventListener('click', () => { element.goTo(1); }); // Navigate to previous slide prevBtn.addEventListener('click', () => { element.goToPrev(); }); // Navigate to next slide nextBtn.addEventListener('click', () => { element.goToNext(); }); // Recalculate width after dynamic changes function updateCarousel() { element.recalculateWidth(); } // Clean up when removing from DOM function removeCarousel() { element.destroy(); } } ``` **Example 3: Destroying carousel instance** ```javascript const instance = HSCarousel.getInstance('#hs-carousel', true); if (instance) { const { element } = instance; const removeBtn = document.querySelector('#hs-remove-btn'); removeBtn.addEventListener('click', () => { // Clean up before removing from DOM element.destroy(); // Now safe to remove the element document.querySelector('#hs-carousel').remove(); }); } ``` ## Events Carousel instances emit events that can be listened to for slide lifecycle hooks. | Event Name | When Fired | Callback Parameter | Description | | --- | --- | --- | --- | | `on:update` | After the active slide changes | `number` (zero-based index of the current slide) | Fires after navigating to the next or previous slide, or after `goTo()` is called. | ### Event Usage Example ```javascript // Get carousel instance const instance = HSCarousel.getInstance('#hs-carousel', true); if (instance) { const { element } = instance; // Listen for slide changes element.on('update', (currentIndex) => { console.log('Active slide:', currentIndex); // Update external indicators, counters, etc. }); } ``` ## Common Patterns ### Pattern 1: Responsive Carousel Display different number of slides at different breakpoints. ```html <div data-hs-carousel='{ "slidesQty": {"xs": 1, "sm": 2, "md": 3, "lg": 4} }'> <!-- Carousel content --> </div> ``` ### Pattern 2: Autoplay Carousel Automatically advance slides at regular intervals. ```html <div data-hs-carousel='{ "isAutoPlay": true, "speed": 5000, "isInfiniteLoop": true }'> <!-- Carousel content --> </div> ``` ### Pattern 3: Programmatic Control Control carousel from external buttons. ```html <div id="hs-carousel-first" data-hs-carousel> <!-- Carousel content --> </div> <button id="hs-go-to-first">Go to First</button> <button id="hs-go-to-last">Go to Last</button> <script> const instance = HSCarousel.getInstance('#hs-carousel-first', true); if (instance) { const { element } = instance; document.querySelector('#hs-go-to-first').addEventListener('click', () => { element.goTo(0); }); document.querySelector('#hs-go-to-last').addEventListener('click', () => { // Assuming 5 slides (indices 0-4) element.goTo(4); }); } </script> ``` ## License Copyright (c) 2026 Preline Labs. Licensed under the [MIT License](https://opensource.org/licenses/MIT).