Svelte
The Svelte wrapper for Embla Carousel provides a seamless way to integrate fluid carousels into your Svelte applications using a custom action. This approach ensures optimal performance by hooking directly into the element's lifecycle.
Installation
To get started, install the embla-carousel-svelte package along with the core library:
npm install embla-carousel-svelte embla-carousel
# or
yarn add embla-carousel-svelte embla-carousel
# or
pnpm add embla-carousel-svelte embla-carousel
Basic Usage
The library exports a useEmblaCarousel action. Apply it to the viewport element of your carousel using the use: directive.
<script>
import useEmblaCarousel from 'embla-carousel-svelte'
let options = { loop: true }
</script>
<div class="embla">
<div class="embla__viewport" use:useEmblaCarousel={{ options }}>
<div class="embla__container">
<div class="embla__slide">Slide 1</div>
<div class="embla__slide">Slide 2</div>
<div class="embla__slide">Slide 3</div>
</div>
</div>
</div>
Accessing the API
To interact with the carousel programmatically (e.g., adding navigation buttons), you need access to the emblaApi instance. The action dispatches a custom event named emblainit once the carousel is ready.
<script>
import useEmblaCarousel from 'embla-carousel-svelte'
let emblaApi
function onInit(event) {
emblaApi = event.detail
}
const scrollNext = () => emblaApi && emblaApi.scrollNext()
const scrollPrev = () => emblaApi && emblaApi.scrollPrev()
</script>
<div class="embla">
<div
class="embla__viewport"
use:useEmblaCarousel
on:emblainit={onInit}
>
<div class="embla__container">...</div>
</div>
<button on:click={scrollPrev}>Prev</button>
<button on:click={scrollNext}>Next</button>
</div>
Reactivity with Stores
Svelte stores are an excellent way to manage carousel state or options across components. Because the useEmblaCarousel action tracks the parameter passed to it, updating a store that is bound to the action will cause Embla to re-initialize with the new configuration.
<script>
import { writable } from 'svelte/store'
import useEmblaCarousel from 'embla-carousel-svelte'
const carouselOptions = writable({ loop: false })
// Toggle loop setting reactively
function toggleLoop() {
carouselOptions.update(opt => ({ ...opt, loop: !opt.loop }))
}
</script>
<div
class="embla__viewport"
use:useEmblaCarousel={{ options: $carouselOptions }}
>
<div class="embla__container">...</div>
</div>
<button on:click={toggleLoop}>
Loop: {$carouselOptions.loop ? 'On' : 'Off'}
</button>
Using Plugins
Plugins are passed as an array in the action parameter. Like options, if the plugin list is updated, the action will handle the re-initialization.
<script>
import useEmblaCarousel from 'embla-carousel-svelte'
import Autoplay from 'embla-carousel-autoplay'
let plugins = [Autoplay({ delay: 4000 })]
</script>
<div
class="embla__viewport"
use:useEmblaCarousel={{ plugins }}
>
<div class="embla__container">...</div>
</div>
TypeScript Support
The package provides types for the action parameters and the custom events. You can use the EmblaOptionsType and EmblaPluginType from the core library to type your configurations.
<script lang="ts">
import useEmblaCarousel from 'embla-carousel-svelte'
import type { EmblaOptionsType } from 'embla-carousel'
const options: EmblaOptionsType = { align: 'start' }
function handleInit(event: CustomEvent<EmblaCarouselType>) {
const api = event.detail
// ...
}
</script>
API Summary
Action Parameters
The useEmblaCarousel action accepts an object with the following properties:
| Property | Type | Description |
| :--- | :--- | :--- |
| options | EmblaOptionsType | Configuration options for the carousel. |
| plugins | EmblaPluginType[] | An array of Embla plugins to activate. |
Custom Events
The viewport element will emit the following events:
| Event | Detail | Description |
| :--- | :--- | :--- |
| on:emblainit | EmblaCarouselType | Emitted when the carousel initializes. Returns the API instance. |